The Spring ’17 Release: A Storm of New Lightning Features

It’s that time of year again – winter is gripping a lot of the Northern Hemisphere, but Salesforce Developers are already looking forward to the fresh offerings of Spring ’17! We’re happy to share some exciting new features to help you build more quickly and efficiently than ever, as well as enhancements to what we’ve introduced in recent releases.

Some of the updates in Spring ’17 for Lightning development include:

  • A LockerService compliant rich text editor
  • Third party JS frameworks availability
  • LockerService and CSPs
  • Unbound expressions, a.k.a. read-only bindings
  • Event handling expansion
  • Token overrides
  • SLDS CSS for Visualforce
  • Lightning Out
  • Lightning API

I’ll walk through these more in detail below.

LockerService Compliant Rich Text Editor

Spring ’17 brings us the Beta of a new Base Lightning Component for creating rich text. Simply use <lightning:inputRichText /> to your component to add the editor. It’s based upon Quill, a LockerService compliant JavaScript library for rich text editing. Rich text editing on the Salesforce platform previously used CKEditor. However, CKEditor does not comply with the strict security requirements of LockerService, hence the need for this new component.

In this example the new rich text editor is combined with other Base Lightning Components.

<aura:component controller="QuickProspectApexController" implements="force:lightningQuickActionWithoutHeader,
 force:hasSObjectName" access="global">
 <aura:attribute name="recordId" type="Id" />
 <aura:attribute name="sObjectName" type="String" />
 <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
 <lightning:card iconName="utility:user" title="Quick Prospect">
 <lightning:layout horizontalAlign="spread" multipleRows="true">
 <lightning:layoutItem size="6" class="slds-p-horizontal--x-small">
 <lightning:input aura:id="firstname" name="firstname" label="First Name" required="true" />
 <lightning:layoutItem size="6" class="slds-p-horizontal--x-small">
 <lightning:input aura:id="lastname" name="lastname" label="Last Name" required="true" minlength="2" />
 <lightning:layoutItem size="12" class="slds-p-horizontal--x-small slds-p-top--x-small">
 <label for="notes" class="slds-form-element__label">Notes</label>
 <lightning:inputRichText aura:id="notes" />
 <lightning:layoutItem size="12">
 <lightning:layout horizontalAlign="center" class="slds-p-top--x-small">
 <lightning:layoutItem >
 <lightning:button variant="brand" aura:id="submitBtn" label="Submit" onclick="{!}" name="foo" />

A Quick Prospect Lightning Container

Not only can you now quickly integrate rich text into your build, support is provided for pasting rich text for any item that is represented in its toolbar- for example Bold, Italic, Bulleted Lists, and Indentations.

Using 3rd Party Frameworks in Lightning

3rd party frameworks such as React or Angular JS are now available for Lightning Component development. I know this will be welcome news to many developers, as I’ve heard this request repeatedly at Dreamforce and World Tour events. While I’m a big proponent of using the Lightning framework whenever possible, I understand that many dev teams already work with Angular JS, React and other popular third-party frameworks, and want to use these with Salesforce. So, in the Spring ’17 release, we’re happy to share <lightning:container>.

The <lightning:container> component creates a wrapper for a single page app (SPA), uploaded as a static resource. <lightning:container> provides an iframe as the host for the content. Even though it’s hosted within an iframe, <lightning:container> provides a message()method to enable bi-directional communication between the SPA and other components on the Lightning page.

<aura:component implements="flexipage:availableForAllPageTypes" access="global" >
<lightning:card iconName="utility:user" title="Lightning Container Example">
<lightning:container src="{!$Resource.myAngularApp + '/www/index.html'}"
onmessage="{!c.handleMessage}" />
<lightning:layout horizontalAlign="center" class="slds-p-top--x-small">
<lightning:layoutItem >
<lightning:button variant="brand" aura:id="submitBtn" label="Submit" onclick="{!c.handleClick}" name="Submit" />
An example of Lightning Container

One important note is that <lightning:container> can only be used in apps which are served from the Lightning domain, This limitation is necessary due to LockerService.


Speaking of LockerService, it is still a Critical Update in Spring ’17, allowing it to be activated/deactivated for the org. With the Summer ’17 release, Salesforce will automatically enable LockerService for all orgs. You’ll notice when you log into your org for the first time in Spring ’17 a notification will appear to remind you of this update.

This release also reinforces the Content Security Policy (CSP) within Developer and Sandbox orgs. CSP is a browser feature that controls the origin of content that can be displayed. What this means for development is that we need to ensure that any 3rd party JavaScript libraries and frameworks used in our Lightning Components and Apps adhere to CSP. You may need to update your version of the library or framework for it to work properly with LockerService turned on.

Unbound Expressions

As developers, we typically don’t give enough thought to how an individual code construct might affect performance. For example, you may be familiar with the magic of bi-directional data binding in Lightning Components for passing values from a parent component to a child component. Something like this:

<aura:attribute name="productName" type="String" default="Lefthanded Wingnut"/>
<c:child childAttr="{!v.productName}" />

What you may not know is this magic is costly in terms of performance, as the framework must monitor both components for changes to the attribute value. Performance gets even worse when there are multiple nested components. To address this, we’ve introduced a new, one-way binding in Spring ’17 called an unbound expression. To turn a bi-directional expression into an unbound expression, we simply change the exclamation point into a hash:

<c:child childAttr="{#v.productName}" />

Now, the attribute in the child component is initialized when the component loads, using the value of the attribute in the main parent component. Changes to the attribute in the child component do not bubble up to the parent attribute, nor do changes to the parent attribute affect the value of the attribute in the child. In other words, this is now a read-only binding, improving your performance.

Event Handling

As a JavaScript developer, I’m used to using typical JavaScript methods like to identify which button or link was clicked by the user. However, prior to this release, the use of and event.currentTarget in a method being called by a Base Lightning Component was limited to orgs in which LockerService was not enabled. Attempting to fire the method with LockerService turned on resulted in an error.

In Spring ’17, we can use the new event.getSource() method to capture the Base Lightning Component which triggered the event. For example:


Token Overrides

The use of tokens is an important best practice in Lightning Component development. If you are unfamiliar with tokens, they are simply “aliases” to a CSS value. For example, let’s say we want to change all of our buttons from the standard blue used in the brand variant of a Lightning Design System (SLDS) button in our Lightning app. This color value is defined as a token. Before Spring ’17, this would have meant writing an extra CSS class that we would need to apply to each instance of the button and then maintain the CSS in future updates. With Spring ’17, we can now override these standard tokens without the need for extra CSS.

We start by creating a tokens bundle — let’s call it “myTokenOverrides”:

<aura:token name="colorBackgroundButtonBrand" value="#C4423E"/>
<aura:token name="colorBorderButtonBrand" value="#C4423E" />

To use the tokens bundle in our app, we simply then need to provide the tokens attribute with a value of the bundle that we just created. Notice that we are using the extends=“force:slds” so that we get the current SLDS CSS:

<aura:application extends="force:slds" tokens="c:myTokenOverrides">
<lightning:button variant="brand" aura:id="submitBtn" label="Submit" />
A standard button with a custom background color

Lightning Design System for Visualforce
Spring ’17 brings us the ability to include SLDS CSS in Visualforce pages with just two simple changes. Ever since Spring ’16, when Lightning Components got access to SLDS without the need for a static resource, Visualforce developers have been asking “what about us?” In other words, people wanted to continue development with Visualforce but wanted the latest and greatest CSS from SLDS – without the trouble of uploading and maintaining a static resource.

To include SLDS CSS into Visualforce pages, begin by replacing the <link> to your static resource version of SLDS with <apex:slds />. Then change the scoping class on the outermost DOM node to “slds-scope.”

// Replace this:
<link rel="stylesheet"
href="{!URLFOR($Resource.SLDS4VF,'assets/styles/salesforce-lightning-design-system-vf.css')}" />
// With this:
<apex:slds />
// Change your custom scoping class from your custom name
<div class="SLDS4VF">

// to
<div class="slds-scope">

You can now also use the $Asset variable to reference assets from SLDS, such as icons and fonts. For example:

<img src="{!URLFOR($Asset.SLDS, 'assets/images/avatar1.jpg')}" alt="Contact Avatar" />

Lightning Out for Unauthenticated Users

One of my favorite features of Lightning is the ability to deploy Lightning Components outside of Lightning Experience using Lightning Out. The only drawback to Lightning Out was the fact that it required a Salesforce login in order to use the component. With Spring ’17, this is no longer the case.

Simply adding the ltng:allowGuestAccess interface to your Lightning Application enables unauthenticated guest access to the application. This also works with Lightning Components for Visualforce.

<aura:application access="GLOBAL" extends="ltng:outApp"
<aura:dependency resource="c:myLightningComponent"/>

There are a couple of things to be aware of when implementing unauthenticated access. First of all, be careful! With guest access enabled, object- and field-level security (FLS) is bypassed. Therefore, security enforcement for CRUD and field-level security must be done manually, i.e. by you, in your Apex Controllers. Next, you will need to make sure that Communities is enabled for the org that is hosting the Lightning Component. You’ll actually use one of your community endpoints as the url for both the Lightning Out script and within the script that activates the Lightning App. In other words, your script URL looks something like:

<script src="https://yourCommunityDomain/communityURL/lightning/lightning.out.js"></script>

Finally, the ltng:allowGuestAccess interface is limited to Lightning Applications, and cannot be used for Lightning Components themselves.

Lightning API

Let’s wrap up by asking a simple question: when is Salesforce not Salesforce? That may sound esoteric, but there are many use cases where a customer wants to leverage their Salesforce data and also wants custom branding or UI. Think about a custom mobile app or a web app developed using another technology such as Angular JS or React. It’s for these specific use cases that Spring ’17 introduces the Lightning API as a Developer Preview.

The Lightning API is a REST API which allows developers to make a single REST call to retrieve, edit or create a Record. The resulting JSON response contains the layout information, metadata, and data for an individual record or collection of records.

For example:


retrieves the information for a single record (collapsed to show more data).

An example of a Lightning API response.

The Lightning API provides a number of resources to allow you to retrieve just the information you are interested in. For example, if you are only interested in the metadata for an object, you could call just that resource — in this case /lapi/object-info.

Alternatively, to create a record, we can simply do a POST request:


and pass a JSON object with the data to insert.

"apiName": "Account",
"fields" : {
"Name": "Local Boxes",
“BillingCity”: “Seattle”,
"BillingState": "WA",
"BillingStreet" : "123 Main Street",
"BillingCountry" : "USA"

For more information about the Lightning API, please have a look at the Lightning API Developer Guide.

More Resources

For even more in-depth information on Lightning development, be sure to check out the newly updated Lightning Components Developer Guide. Also, we’ve posted an on-demand replay of the Spring ’17 Developer Preview broadcast below. We can’t wait to hear your thoughts on these updates!

tagged , Bookmark the permalink. Trackbacks are closed, but you can post a comment.
  • Mohammed Riaz

    How we can change it for the Roles and Hierarchy it will be helpful for all developer Community