Easy Spaces is a fictional event management company that creates and manages custom pop-up spaces (like cafés or game rooms) for companies and individuals, in their offices and homes. This reference application shows how Easy Spaces uses Salesforce to create and manage reservations, and match customers to the right kind of pop-up space.
Easy Spaces demonstrates how to build flexible, user-centric experiences. It also demonstrates how to manage the source for your apps with unlocked packages and use modular source control structures for your apps.
In this post, we’ll explore some of the key features of the Easy Spaces application and walk through sample code, and share how you can install and explore the app yourself.
What’s in this release?
Easy Spaces is based on the WeWork app shared during the TrailheaDX 2018 Opening Keynote. In the Summer 2018 initial release, Easy Spaces is all about integrating Lightning Flow and the Lightning Component framework with the Workspace API and console navigation to create user-centered apps that keep complex processes simple. The Easy Spaces application uses unlocked packages and object-agnostic design to illustrate possibilities for modularizing your Salesforce apps.
At the core of this initial release is the ‘Space Management’ Lightning app. This app uses console navigation and custom application pages to provide a centralized and simplified way to manage reservations and match customers to the right pop-up space.
You can take a quick video tour here.
The Reservation Manager gives Easy Spaces one place to manage how they help customers who need get started with a reservation:
The Spaces Designer is a centralized workspace to help match customers to the best type of pop-up:
Let’s look at how these pages, and the application itself, are built.
Lightning Flow and Base Components
Lightning Flow is central to the functionality of both the Spaces Designer and Reservation Manager. The spaceDesigner and reservationHelper components integrate dynamic flow interviews with other components on the page, using the
<lightning:flow> base component.
The spaceDesigner component (in action above), dynamically begins a flow interview based on user interaction with the other components on the page. The markup for the flow component is simple:
The actual creation of the flow takes place in the component’s helper:
- Lines 3,4: These lines set values for the flow’s input variables in JSON format. The
nameattribute should match the variable name defined in the flow.
- Line 7: The startFlow() method is provided by the
The spaceDesigner and reservationHelper flows both use custom Lightning components with the
lightning:availableForFlowScreens interface to create rich and interactive screens for users. This interface also gives these components access to flow navigation actions, which allow you to create custom options for users.
For example, the customerDetails component shows users a ‘Draft Reservation’ button:
The button invokes a method, which triggers a flow navigation action:
- Line 3: The
navigateFlowattribute is provided by the
- Line 4: The
navigate()method is also provided by the
lightning:availableForFlowScreensinterface. The component uses the string value “NEXT” to invoke the same navigation action as the native ‘Next’ button, provided by flow.
Check out the smartGallery and customerDetails components for examples of how to work with flow navigation actions.
<lightning:recordForm> component lets Easy Spaces quickly and easily display record-based information throughout the application. It can show information in read-only or editable formats, with built-in respect for field-level security.
In the picture above, the ‘Primary Contact for Reservation’ section of is this base component at work in the customerDetails component:
- Line 4: The
fieldsattribute determines what fields to display. The component handles styling for each field based on its data type.
- Line 5: The
modeattribute determines the behavior of the component. Choosing ‘view’ displays information in an editable format.
- Line 7: The
onloadattribute lets you execute custom logic when the component’s data loads.
- Lines 2, 3, 4: The dynamic syntax in this example allows the component to display different sObject records. (More detail on how this works in the ‘Object-Agnostic Design’ section.)
Console navigation and Workspace API
Because the Space Management Lightning app uses console navigation, components in the app will display different behavior when users trigger standard actions like
This change in component behavior is based entirely on the navigation settings in Lightning App Builder, rather than any specific changes component markup:
Components in console apps can implement custom navigation behaviors via the Workspace API, which allows manipulation of tabs and subtabs. Components access this API by including the
<lightning:workspaceAPI> component in their markup.
The openRecordAction component is an example of this:
The interaction with the API takes place in the openRecordActionController:
- Component markup, line 1: The
lightning:availableForFlowActionsinterface, new in Summer ’18, allows components to be used in flows as a new type of resource called Local Actions. This means the openRecordAction can be used to give a flow interview access to the WorkspaceAPI and custom navigation behavior.
- Controller.js, line 1: Because the component uses the
lightning:availableForFlowActionsinterface, the controller uses
invokeas the name of the method a flow interview should access.
- Controller.js, lines 4-12: The controller uses the
<lightning:workspaceAPI>component to access navigation methods provided by the API. The controller invokes the
openTab()method, providing a URL in the new Summer ’18 standardized format as the target for the new tab. The
focusTab()method ensures the newly opened tab receives immediate focus, rather than opening in the background.
A flow can then use a simple Decision step to control whether or not the Local Action should be used when ending the interview:
You’ll see examples of how to use the Workspace API to control app behavior, including how to refresh tabs, in the spaceDesigner and reservationHelper components.
Easy Spaces uses design tokens to give custom components uniform styling. You can see this in the pill custom component, which turns a brand-specific green when selected:
In the component’s css, this color is expressed as a token value:
The custom tokens for Easy Spaces are defined in the defaultTokens bundle:
- Line 1: Using
extends="force:base"in the tokens markup gives Easy Spaces components access to a variety of standard tokens provided by Salesforce.
- Lines 2,3: The tokens defined on these lines are the custom tokens defined by Easy Spaces for use throughout their application.
Easy Spaces, like many companies, has processes that cut across different objects. Regardless of whether a person’s data is in the system as a Lead or a Contact, people need to be able to help a customer make reservations and find the right space for their events quickly and easily. Easy Spaces uses object-agnostic design patterns to accomplish this.
We’ve already looked at an example of this with the customerDetails component.
The customerList component is another example. The image below shows two instances of the component on an application page, associated with two different sObject types:
The sObject type the component should display is set by a design parameter in the Lightning App Builder.
The markup for the component itself is simple:
The customerTile component (on line 12), displays record-level detail. It uses the
<lightning:tile> base component and accepts a generic object:
Easy Spaces builds these object-agnostic components on top of services provided by Custom Metadata Types and Apex. These services create a standardized pattern Lightning components can use to handle and display customer record data.
The backbone of these services in Apex is the customerServices class. This class uses an inner class to define a standardized ‘Customer’, with the attributes common to all Easy Spaces customers, no matter the object:
@auraEnabledvariables allow Lightning components (and other parts of the Easy Spaces application) a standardized dot notation for field-level attributes. The syntax becomes
Contact.MailingCity. You can see this dot notation at work in the customerTile.
.isNotEmpty()checks allow for flexible usage of the Customer wrapper object across the application. Not every component has to use every attribute.
The class also exposes a
getCustomerFields method which allows components or other parts of the system to pass in a specific sObject name and receive back a ‘Customer’ object, with the API names of the fields holding ‘Customer’ data for that particular sObject:
- The query refers to a Custom Metadata Type called Customer Fields, which holds information like field API names for customer data in the Easy Spaces schema.
QualifiedAPINameattribute is what makes sure schema information returns in a format (i.e. ‘My_Custom_Field__c’) that can be used by
- This method returns a
Customerwrapper object so that calling components can use a standardized dot notation to access schema information:
Modular design and unlocked packaging
Easy Spaces also shows how you can build applications on top of granular units or modules of metadata. Specific features, like the use of design tokens or object-agnostic patterns, add to the modularity of Easy Spaces by making parts of the code base reusable and flexible. But you’ll get the best understanding of what modular design really means for Easy Spaces by looking at how Easy Spaces is organized in source control (link below).
The process of building the Easy Spaces application is the basis for our Getting Started with Modular Development and Unlocked Packaging series. To install the Easy Spaces application yourself, you’ll actually install several unlocked packages rather than one giant package.
These packages are maintained as a distinct folders within a unified project in source control. You can see dependencies between packages by looking at the project’s
sfdx-project.json file. For more insight into the process behind organizing metadata into these distinct package modules, check out this post.
The source code and installation instructions are available in this GitHub repository.
The Easy Spaces app illustrates how you can combine the power of Lightning Flow, the Lightning Component framework and console navigation to create dynamic and user-centric applications. And thanks to the power of unlocked packages and Salesforce DX, you can explore this sample app yourself, quickly and easily.