Lightning Components Workshop v2

Preview:

Citation preview

Building Lightning ComponentsChristophe CoenraetsDeveloper Evangelist

#TrailheadLive@ccoenraets

http://developer.salesforce.com/trailhead/projects

What you will do

Build an Account Locator built as a a set of loosely coupled components communicating through events Explore different deployment options:• Lightning App• Salesforce1 App• App Builder Composition

AccountMap

AccountList

AccountLocator

AccountListItem

Step 1:Setting Up Your Environment

1. Sign up for a Developer Edition Org2. Enable My Domain3. Deploy to Users

Challenge

Step 2:Enabling Geolocation on Accounts

1. Add a geolocation field to the Account object2. Enter sample data

Challenge

Step 3:Creating an Aura-Enabled Controller

Visualforce Page-Centric Model

1. Browser requests page

Client Server

4. Browser renders html

2.Server executes Apex code3.Server returns page (html + data)

Show different data? Back to 1Show different view? Back to 1

Pros1. Proven model2. Productivity. Easy to implement3. Naturally splits large apps into small, manageable units (pages)

Caveats4. Limited interactivity5. Higher latency

Visualforce Page Centric Model

Lightning App-Centric Model

1. Browser requests Component

Client Server

3. Browser builds UI with JavaScript

4. Browser requests data

7. Back to 3

2.Server returns Component Bundle

5. Server executes Apex6.Server returns data (data only!)

Show different data? Back to 4Show different view? Back to 3

Pros• Enables highly interactive/immersive user experiences• Less page refreshes• Tightly integrated (no iframe)• Composable

Caveats• Higher learning curve compared to vanilla Visualforce pages• Higher level of complexity. Building an app is generally more complex than building a

page

Lightning Components App Centric Model

Creating an Aura-Enabled Apex Controller

public with sharing class AccountController {

@AuraEnabled public static List<Account> findAll() { return [SELECT id, name FROM Account]; }

}

* You should add code to enforce CRUD and FLS

1. Create an Aura-enabled Apex controller named AccountController

2. Add a findAll() method that returns accounts that have location information

Challenge

Step 4:Creating the AccountLocator

Component

Anatomy of a Lightning Component

<aura:component controller="AccountController">

<div>

<div>AccountMap goes here</div>

<div>AccountList goes here</div>

</div>

</aura:component>

Component Parts: Component

UI MarkupData bindingAttributes

Component

Component Parts: Style

UI MarkupData bindingAttributes

ComponentStyle

EncapsulatedCSS

1. In Lightning Applications2. In the Salesforce1 app3. In App Builder

Where can I use Lightning Components?

Using a Lightning Component in a Lightning App

1. Create a Lightning AppFile > New > Lightning Application

2. Embed the Lightning Component<aura:application>

<c:AccountLocator/>

</aura:application>

Useful for creating fullscreen apps or for testing components during development

Using a Lightning Component in the Salesforce1 App

1. Implement the force:appHostable interface<aura:component implements="force:appHostable">

2. Create a Tab3. Add the Tab to Mobile Navigation

1. Create the AccountLocator component2. Add AccountLocator to the Salesforce1 App menu

Challenge

Step 5:Creating the AccountList

Component

Attributes

• The data of the component• Available anywhere in the component• Examples:

<aura:attribute name="price" type="Number"/>

<aura:attribute name="title" type="String"/>

<aura:attribute name="account" type="Account"/><aura:attribute name="accounts" type="Account[]"/>

Data Binding {! }

<aura:attribute name="account" type="Account"/>

<p>{!v.account.Name}</p>

Initial value of <p> is set to the value of account.Name Value of <p> automatically updated when value of account.Name changes

Bidirectional Data Binding

<aura:attribute name="price" value="100" type="Number"/>

<ui:inputNumber label="Principal:" value="{!v.price}"/>

Initial value of inputNumber is set to value of attribute (100) Value of price attribute is updated when user types new value in inputNumber

Component Parts: Controller

UI MarkupData bindingAttributes

Component

EventHandlers

ControllerStyle

EncapsulatedCSS

<aura:attribute name="counter" type="Number" default="0"/><ui:button label="Click me" press="{!c.handleClick}"/><div>{!v.counter}</div>

handleClick: function(component, event) { var counter = component.get("v.counter"); counter = counter + 1; component.set("v.counter", counter);}

Com

pone

ntCo

ntro

ller

Event Handler ExampleCounter

Event Handler ExampleRetrieving Data on Init

<aura:attribute name="accounts" type="Accounts[]"/><aura:handler name="init" value="{!this}" action="{!c.doInit}" />

doInit : function(component, event) { var action = component.get("c.findAll"); action.setCallback(this, function(a) { component.set("v.accounts", a.getReturnValue()); }); $A.enqueueAction(action);}

Com

pone

ntCo

ntro

ller

Iterating through a List

<aura:attribute name="accounts" type="Account[]"/>

<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>

<ul>

<aura:iteration items="{!v.accounts}" var="account">

<li>{!account.Name}</li>

</aura:iteration>

</ul>

Nested Component

• A component used in another component• AccountListItem Example:<aura:component>

<aura:attribute name="account" type="Account"/>

<li>{!v.account.Name}</li>

</aura:component>

Using a Nested Component

<aura:attribute name="accounts" type="Account[]"/>

<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>

<ul>

<aura:iteration items="{!v.accounts}" var="account">

<c:AccountListItem account="{!account}"/>

</aura:iteration>

</ul>

1. Create the AccountList component responsible for displaying the list of accounts

2. Create the AccountListItem component that you nest inside AccountList to render individual accounts in the list

Challenge

Step 6:Creating the AccountMap Component

• External JavaScript libraries and CSS style sheets must be loaded as static resources

• Use the <ltng:require> tag to load them• Loading is asynchronous• afterScriptLoaded event is triggered after files have been succesfully

loaded

Loading External JavaScript Libraries and CSS Files

Loading External JavaScript Libraries

<ltng:require scripts="/resource/leaflet/leaflet.js"/>

Loading External CSS Style Sheets

<ltng:require styles="/resource/leaflet/leaflet.css" />

Loading JavaScript Libraries and CSS Style Sheets

<ltng:require scripts="/resource/leaflet/leaflet.js"

styles="/resource/leaflet/leaflet.css" />

Using the afterScriptLoaded Event

<ltng:require scripts="/resource/leaflet/leaflet.js" styles="/resource/leaflet/leaflet.css" afterScriptsLoaded="{!c.renderMap}" />

1. Load leaflet JS library2. Load Leaflet CSS3. Render the map when files are loaded

Challenge

Step 7:Intercomponent Communication

Intercomponent Communication

Application Event Broker

Event Object

<aura:handler event="c:AccountsLoaded" action="{!c.accountsLoadedHandler}"/>

<aura:registerEvent name="loaded" type="c:AccountsLoaded"/>

var event = $A.get("e.c:AccountsLoaded");event.setParams({"accounts": accounts});event.fire();

AccountMapAccountList

Creating the AccountsLoaded Event

<aura:event type="APPLICATION">

<aura:attribute name="accounts" Type="Account[]"/>

</aura:event>

1. Create the AccountsLoaded Event2. Trigger the AccountsLoaded Event in AccountList3. Handle the AccountsLoaded Event in AccountMap

Challenge

Step 8:Using Events to Center the Map

Intercomponent Communication

Application Event Broker

Event Object

<aura:handler event="c:AccountSelected" action="{!c.accountSelectedHandler}"/>

<aura:registerEvent name="select" type="c:AccountSelected"/>

var event = $A.get("e.c:AccountSelected");event.setParams({"account": account});event.fire();

AccountMapAccountList

1. Create the AccountSelected event2. Trigger the AccountSelected event in AccountList3. Handle the AccountSelected event in AccountMap and center the

map on the selected account location

Challenge

Step 9:Interacting with the Salesforce1 App

1. Lightning Components enable you to extend standard features2. Don't reinvent the wheel

For example, if your component needs an account details view: use the standard one, don't create your own

3. Navigation between standard features and custom components should be smooth and feel integrated: users shouldn't notice they are switching between standard and custom features

4. Platform events allow you to integrate your custom components into the standard experience

Salesforce1 Integration

Firing a Platform Event

var event = $A.get("e.force:navigateToSObject");

event.setParams({

"recordId": accountId

});

event.fire();

This event will be handled be the Salesforce1 app which will then navigate to the account's details view

Component Parts: Helper

UI MarkupData bindingAttributes

Component

EventHandlers

Controller

SharedLogic

HelperStyle

EncapsulatedCSS

When a user clicks a marker on the map, load the default Salesforce1 details view for the selected account

Challenge

Step 10:Using Components in App Builder

Using a Lightning Component in App Builder

1.Implement the flexipage:availableForAllPageTypes interface

<aura:component implements="flexipage:availableForAllPageTypes">

2.Create a component description in the Design part

<design:component label="AccountList">

</design:component>

3.Enable App Builder for Lightning Experience (PILOT)

4.Drag the component from the component palette in App Builder

Compose AccountList and AccountMap in App Builder

Challenge

Summary

UI MarkupData bindingAttributes

Component

Design Descriptor

EventHandlers

Controller

SharedLogic

HelperStyle

Custom Rendering

Renderer

EncapsulatedCSS

App Builder