Skip to main content

Maintain Your Platform Developer I Certification for Winter ’23

Learning Objectives

After completing this unit, you’ll be able to:

  • Utilize flow and process run-time improvements in API Version 54.0.
  • Work with org-specific domain hostnames and information.
  • Create notifications with new alert, confirm, and prompt modules.
  • Create scratch orgs more easily with Org Shape.
  • Create overlays with the new modal component.
  • Call invocable actions from Apex.

Salesforce Certification

If you hold the Platform Developer I credential, keep in mind that you need to complete this module by the due date to maintain your certification. Another important part of maintaining your credential is ensuring your Trailhead and Webassessor accounts are linked.

Interested in learning more about getting certified? Check out the Salesforce Platform Developer I credential.

Note

While anyone can earn this badge, this module is designed for those who hold the Platform Developer I certification.

Protect the Integrity of Your Certification

The quality of our certification exams and the value our credentials provide are our highest priority. Protecting the security and confidentiality of our exams is essential to providing our customers with credentials that are respected and industry-leading.

As a participant of the Salesforce Certification Program, you’re required to accept the terms of the Salesforce Credential and Certification Program Agreement. Please review the Salesforce certification exam-taking policies in the Salesforce Credential and Certification Program Agreement and Code of Conduct Trailhead Help article for more details.

Salesforce introduced a ton of great feature enhancements over the past year. Let’s take a look at some of the more important ones.

Utilize Flow and Process Run-Time Improvements in API Version 54.0

These updates affect only flows and processes that are configured to run on API version 54.0 or later. Versioned updates let you test and adopt run-time behavior changes for individual flows and processes at your convenience. To change the run-time API version of a flow, open it in Flow Builder, click Save As, then "Show Advanced". Select the API Version for Running the Flow and Save, then activate the flow. To change the run-time API version of a process, open it in Process Builder and edit its properties.

Where: This change applies to Lightning Experience, Salesforce Classic, and all versions of the mobile app in Essentials, Professional, Enterprise, Performance, Unlimited, and Developer editions.

After-Save Record-Triggered Flows Now Run Before Entitlements Are Executed

Now in the order of execution, after-save flows run before entitlements are executed, so that entitlements can include the record updates that after-save flows make. In API version 53.0 and earlier, after-save record-triggered flows still run after entitlements are executed.

In API version 54.0, after-save flows now run immediately after processes created via Process Builder, without entitlements executing between them. For Salesforce admins who migrate to flows from processes, this change helps to ensure consistent results for entitlements.

Approval and Time-Based Workflow Field Updates Now Execute Before-Save and After-Save Record-Triggered Flows

Field update actions associated with approval processes and time-dependent actions in workflow rules now execute before-save and after-save record-triggered flows so that these update actions can incorporate flow automation. In API version 53.0 and earlier, these field update actions don’t execute flows, so certain record updates don’t trigger corresponding flows. Workflow rules and processes created via Process Builder are unaffected.

As a result of this change, flows now run slightly more often and whenever Apex runs. This difference is most apparent in the execution of time-based workflow and approvals. For other types of save operations, there’s no impact.

Flow triggers are executed only one time per entity per transaction. Even a record update doesn’t execute a flow trigger a second time on the same entity. Also, flow triggers are executed when you use the Data Import Wizard and specify to trigger workflow rules and processes when the imported records meet the criteria.

These changes provide for a more straightforward understanding of the different scenarios in which before- and after-save record-triggered flows execute. For example, now when a field update action occurs, it’s easier to see when a flow executes.

A Flow Error Email Is Now Sent for an Update Record Element That References an Invalid Record Variable

An error email is sent if a flow executes an Update Record element that references an invalid record ID on a record variable. Previously, no flow error email was sent.

Work with Org-Specific Domain Hostnames and Information

When you change your org’s My Domain name due to a brand change or you enable enhanced domains, the domains that Salesforce hosts for your org change. To insulate your code against these changes, determine the hostnames for these domains with the new System.DomainCreator Apex class.

You can also get information about the domains that Salesforce hosts for your org with the new System.Domain class. Or use a URL or hostname to obtain information about the associated domains with the new System.DomainParser class.

Where: This change applies to Lightning Experience and Salesforce Classic in Enterprise, Performance, Unlimited, and Developer editions.

System.DomainCreator Class

To determine the hostnames for the domains that Salesforce hosts for your org, use the methods in the new System.DomainCreator class.

For example, the getOrgMyDomainHostname() method returns the hostname for your org’s My Domain login URL and the getLightningHostname() method returns the hostname for your org’s Lightning pages. And the getExperienceCloudSitesHostname() method returns the hostname for the system-managed domain for your org’s Experience Cloud sites.

System.Domain Class

To obtain information about domains that Salesforce hosts for your org, use the methods in the new System.Domain class.

For example, for a sandbox domain, the getSandboxName() method returns the name of the sandbox. And the getDomainType() method returns the associated System.DomainType enum value, which represents the type of domain, such as CONTENT_DOMAIN, EXPERIENCE_CLOUD_SITES_DOMAIN, or LIGHTNING_DOMAIN.

System.DomainParser Class

To use a URL or hostname to obtain information about the domains that Salesforce hosts for your org, use the methods in the new System.DomainParser class.

Use the parse(hostname) method to parse a Salesforce-owned hostname for your org, such as MyDomainName.my.site.com and extract information about the domain. Use the parse(url) method to parse a Salesforce URL for your org, such as https://MyDomainName.my.site.com.

Create Notifications with New Alert, Confirm, and Prompt Modules

Use the new modules LightningAlert, LightningConfirm, and LightningPrompt instead of native APIs to create notifications from your Lightning web components. Chrome and Safari plan to end support for cross-origin use of the window.alert(), window.confirm(), and window.prompt() native APIs. Each new module creates a modal that functions like its API counterpart and works in cross-origin iframes.

Where: This change applies to Lightning Experience and all versions of the Salesforce mobile app in all editions.

How: Unlike the window.*() APIs, these modules' .open() functions don’t halt execution on the page, and they each return a promise. Use async/await or .then() for any code that you want to execute after the modal closes.

These examples show how to use LightningAlert, LightningConfirm, and LightningPrompt in Lightning web components. See New and Changed Aura Components for examples using Aura syntax with the lightning:alert, lightning:confirm, and lightning:prompt components.

This example creates an alert modal with an error message and OK button. The .open() function returns a promise that resolves when the user clicks OK.

<!-- c/myApp.html -->
<template>
    <lightning-button onclick={handleAlertClick} label="Open Alert Modal">
    </lightning-button>
</template>
// c/myApp.js
import { LightningElement } from 'lwc';
import LightningAlert from 'lightning/alert';
export default class MyApp extends LightningElement {
    async handleAlertClick() {
        await LightningAlert.open({
            message: 'this is the alert message',
            theme: 'error', // a red theme intended for error states
            label: 'Error!', // this is the header text
        });
        //Alert has been closed
    }
}

This example creates a headerless confirm modal with two buttons, OK and Cancel. The .open() function returns a promise that resolves to true when the user clicks OK and false when they click Cancel.

<!-- c/myApp.html -->
<template>
    <lightning-button onclick={handleConfirmClick} label="Open Confirm Modal">
    </lightning-button>
</template>
// c/myApp.js
import { LightningElement } from 'lwc';
import LightningConfirm from 'lightning/confirm';
export default class MyApp extends LightningElement {
    async handleConfirmClick() {
        const result = await LightningConfirm.open({
            message: 'this is the prompt message',
            variant: 'headerless',
            label: 'this is the aria-label value',
            // setting theme would have no effect
        });
        //Confirm has been closed
        //result is true if OK was clicked
        //and false if cancel was clicked
    }
}

This example creates a prompt modal with a header, message, and two buttons. If the user inputs text and clicks OK in the prompt, the .open() function returns a promise that resolves to the input value, but if the user clicks Cancel it resolves to null.

<!-- c/myApp.html -->
<template>
    <lightning-button onclick={handlePromptClick} label="Open Prompt Modal">
    </lightning-button>
</template>
// c/myApp.js
import { LightningElement } from 'lwc';
import LightningPrompt from 'lightning/prompt';
export default class MyApp extends LightningElement {
    handlePromptClick() {
        LightningPrompt.open({
            message: 'this is the prompt message',
            //theme defaults to "default"
            label: 'Please Respond', // this is the header text
            defaultValue: 'initial input value', //this is optional
        }).then((result) => {
            //Prompt has been closed
            //result is input text if OK clicked
            //and null if cancel was clicked
        });
    }
}

Create Scratch Orgs More Easily with Org Shape

Features, settings, edition, limits, and licenses determine what we refer to as an org’s shape. We know it’s not easy to build a scratch org definition that mirrors the features and settings in your production org. With Org Shape for Scratch Orgs, you can leave building the scratch org definition to us. After you capture the org’s shape, you can spin up scratch orgs based on it.

Where: This change applies to Lightning Experience, Salesforce Classic, and all versions of the mobile app in Developer, Group, Professional, Enterprise, and Unlimited editions.

How: Enable Org Shape for Scratch Orgs in both the source org and the Dev Hub org. If you don't have access to the Org Shape Setup page in these orgs, ask your Salesforce admin for help.

Create Overlays with the New Modal Component

Use modals to interrupt a user’s workflow and draw attention to an important message. A modal, which displays the message on top of the current app window, requires a user to interact with it to regain control over the app.

Where: This feature is available for Lightning Experience in all editions.

How: To create a modal component, import LightningModal from lightning/modal in your JavaScript file. Then, create a component class that extends LightningModal.

/* c/myModal.js */
import { api } from 'lwc';
import LightningModal from 'lightning/modal';
export default class MyModal extends LightningModal {
    handleOkay() {
        this.close('okay');
    }
}

This component doesn’t use a lightning-modal tag. Instead, the modal’s HTML template uses helper lightning-modal-* components to make the modal’s header, footer, and body. The lightning-modal-body component is required, and the others are optional.

<!-- c/myModal.html -->
<template>
    <lightning-modal-header label="My Modal Heading"></lightning-modal-header>
    <lightning-modal-body>This is the modal’s contents.</lightning-modal-body>
    <lightning-modal-footer>
        <lightning-button label="OK" onclick={handleOkay}></lightning-button>
    </lightning-modal-footer>
</template>

Call Invocable Actions from Apex

Invocable.Action is a new Apex class that allows you to call invocable actions from Apex code.

Where: This change applies to Lightning Experience and Salesforce Classic in Enterprise, Unlimited, Developer, and Database.com editions.

How: Reference Invocable.Action in your Apex code.

For example, this class calls the standard invocable action chatterPost to post a message to the current user’s feed. 

public class MyApexClass {
    public void postToChatter(String recordId) {
        Invocable.Action action = Invocable.Action.createStandardAction('chatterPost');
        action.setInvocationParameter('text', 'This is an example Chatter post.');
        action.setInvocationParameter('subjectNameOrId', recordId);
        List<Invocable.Action.Result> results = action.invoke();
        if (results.size() > 0 && results[0].isSuccess()) {
            System.debug('Created feed item with ID: ' +
            results[0].getOutputParameters().get('feedItemId'));
        }
    }
}

This class calls a custom invocable action named Doubler that returns a number that’s twice the input value.

public class MyApexClass {
    public void doubler (Double input) {
        Invocable.Action action = Invocable.Action.createCustomAction('apex', 'Doubler');
        action.setInvocationParameter('input', 1);
        List<Invocable.Action.Result> results = action.invoke();                                          
        if (results.size() > 0 && results[0].isSuccess()) {
            System.debug('Result is: ' + results[0].getOutputParameters().get('output'));
        }
    }
}

Resources

Keep learning for
free!
Sign up for an account to continue.
What’s in it for you?
  • Get personalized recommendations for your career goals
  • Practice your skills with hands-on challenges and quizzes
  • Track and share your progress with employers
  • Connect to mentorship and career opportunities