Présentation du Bordeaux Salesforce Developer Group.
Apprenez à développer vos premiers Lightning Web Components.
Appréhendez la migration de vos composants Lightning Aura vers LWC.
1. Workshop – Lightning Web Components
Bordeaux Salesforce Developer Group
@martinlezer
Martin Lezer, Group Leader
2. Productivité améliorée
Utilisation des langages modernes du Web: ES6+,
Elements personnalisés, et Shadow DOM
Conçu pour la performance
Plus de code exécuté par le navigateur au lieu
d’abstractions Javascript pour une expérience plus
rapide
Compatible et facile à utiliser
Exécuté simultanément avec des composants Lightning
existants
Introduction - Lightning Web Components
Un nouveau modèle de programmation construit sur les standards du Web
5. Installation de l’environnement
• Utilisez le lien correspondant à votre environnement
Installation de Salesforce DX
Operating System
Link to Installer
macOS https://sfdc.co/sfdx_cli_osx
Windows 32-bit https://sfdc.co/sfdx_cli_win
Windows 64-bit https://sfdc.co/sfdx_cli_win64
Debian/Ubuntu 64 https://sfdc.co/sfdx_cli_linux
Download the archive from one of the URLs in the manifest, extract the archive, then run the ./install script.
Debian/Ubuntu x86 https://sfdc.co/sfdx_cli_linux_x86
Download the archive from one of the URLs in the manifest, extract the archive, then run the ./install script.
6. • Téléchargez l'installeur de Visual Studio Code : https://code.visualstudio.com/
• Installez Visual Studio Code grâce à l'installeur
• Lancez Visual Studio Code à la fin de l'installation
• Cliquez sur l'icône dans la barre de navigation de gauche
• Cherchez l’extension appelée « Salesforce Extension Pack »
• Installez l’extension
• Rechargez Visual Studio Code à la fin de l’installation
Installation de Visual Studio Code
Installation de l’environnement
8. • Fichier HTML:
• nommé suivant la convention: <component>.html
• avec comme balise racine: <template>
• Fichier Javascript:
• nommé suivant la convention: <component>.js
• chaque fichier de composant doit inclure le code suivant:
Structure des fichiers d’un composant
Les bases
import { LightningElement } from 'lwc’;
export default class MyComponent extends LightningElement {
}
// Your code here
9. • Equivalent aux attributs sur Aura
• Variables Javascript accessibles à certaines
conditions par le template HTML
Propriétés
Les bases
import { LightningElement, api, track } from 'lwc’;
export default class TodoItem extends LightningElement {
@api itemTitle = ''; // public
itemId = ''; // private
@track state = { x: 100, y: 100 }; // internal and reactive
}• Différents types de propriétés:
• privée: variable seulement utilisée dans le
code Javascript
• réactives: si la valeur d’une variable change,
elle est mise à jour dans le template
• publique: accessible par un composant parent
• tracked: variable privée
<template>
<div class="view">
<label>{itemName}</label>
</div>
</template>
Controller Javascript
Template
10. • Les expressions Aura complexes sont transformées en code Javascript
• Utilisation de getters dans le code Javascript
Expressions HTML et logique Javascript
Les bases
<aura:if isTrue="{!v.page > 1}">
<lightning:buttonIcon iconName="utility:left" variant="border" onclick="{!c.previousPage}"/>
</aura:if>
Code Aura Framework
Code LWC
<template if:false={isFirstPage}>
<lightning-button-icon icon-name="utility:chevronleft" onclick={previousHandler}></lightning-button-icon>
</template>
import { LightningElement, api } from 'lwc’;
export default class Paginator extends LightningElement {
/** The current page number. */
@api pageNumber; get isFirstPage() {
return this.pageNumber === 1;
}
}
13. • Utilisation de CSS standard
• Limité au contexte du composant
• Inclus dans un fichier css rattaché au composant
CSS
Les bases
<template>
<h1>To Do List (h1)</h1>
</template>
h1 {
font-size: xx-large;
}
Template
CSS
14. <!-- contactListItem.html -->
<template>
<a href="#" onclick={selectHandler}>
<lightning-layout vertical-align="center">
<lightning-layout-item>
<img src={contact.Picture__c}></img>
</lightning-layout-item>
<lightning-layout-item padding="around-small">
<p>{contact.Name}</p>
</lightning-layout-item>
</lightning-layout>
</a>
</template>
• Utilisation des standards du web avec le
constructeur CustomEvent()
• Un composant parent peut capter un
événement d’un enfant
Evénements personnalisés
Les bases
• L’enfant défini le nom du l’événement ainsi
que les données associées. Ensuite, il le
dispatch avec la méthode
EventTarget.dispatchEvent()
• Le parent définit une fonction handler de
l’événement
Template enfant
Javascript enfant
// contactListItem.js import { LightningElement, api } from 'lwc’;
export default class ContactListItem extends LightningElement {
@api contact;
selectHandler(event) {
// Prevents the anchor element from navigating to a URL.
event.preventDefault();
// Creates the event with the contact ID data.
const selectedEvent = new CustomEvent(
'selected’,
{ detail: this.contact.Id }
);
// Dispatches the event.
this.dispatchEvent(selectedEvent);
}
}
18. L’intéraction avec les données
Wire Service
• Surcouche du Lightning Data Service
• Permet de lire ou créer un enregistrement sans appel Apex, seulement du Javascript
• Appelable grâce à l’annotation @wire
• Les références vers les objets et champs utilisés doivent être importées afin de:
• empêcher la suppression de l’objet ou du champ
• vérifier à l’exécution que les références existent
• vérifier l’inclusion des champs et objets utilisés dans le change set
• L’import des références se fait sous la forme suivante:
import objectName from '@salesforce/schema/object';
import FIELD_NAME from '@salesforce/schema/object.field';
19. L’intéraction avec les données
Wire Service (suite)
• Lecture d’un enregistrement
<template>
<lightning-card title="My Contact Record" icon-name="standard:contact">
<template if:true={contact.data}>
<div class="slds-m-around_medium">
<p>{name}</p>
<p>{title}</p>
<p><lightning-formatted-phone value={phone}></lightning-formatted-phone></p>
<p><lightning-formatted-email value={email}></lightning-formatted-email></p>
</div>
</template>
</lightning-card>
</template>
Template
20. L’intéraction avec les données
Wire Service (suite)
• Lecture d’un enregistrement (suite): utilisation de la méthode
// wireGetRecordDynamicContact.js
import { LightningElement, api, wire } from 'lwc’;
import { getRecord } from 'lightning/uiRecordApi’;
const FIELDS = [ 'Contact.Name', 'Contact.Title', 'Contact.Phone', 'Contact.Email', ];
export default class WireGetRecordDynamicContact extends LightningElement {
@api recordId;
@wire(getRecord, { recordId: '$recordId', fields: FIELDS }) contact;
get name() {
return this.contact.data.fields.Name.value;
}
get title() {
return this.contact.data.fields.Title.value;
}
get phone() {
return this.contact.data.fields.Phone.value;
}
get email() {
return this.contact.data.fields.Email.value;
}
}
Javascript Controller
getRecord
21. L’intéraction avec les données
Wire Service (suite)
• Création d’un enregistrement
Template
<template>
<lightning-card title="LdsCreateRecord" icon-name="standard:record">
<div class="slds-m-around_medium">
<lightning-input label="Id" disabled value={accountId}></lightning-input>
<lightning-input label="Name" onchange={handleNameChange} class="slds-m-bottom_x-small"></lightning-input>
<lightning-button label="Create Account" variant="brand" onclick={createAccount}></lightning-button>
</div>
</lightning-card>
</template>
22. L’intéraction avec les données
Wire Service (suite)
• Création d’un enregistrement:
Javascript Controller
• Utilisation de la méthode
createRecord()
import { LightningElement, track } from 'lwc’;
import { createRecord } from 'lightning/uiRecordApi’;
import { ShowToastEvent } from 'lightning/platformShowToastEvent’;
import ACCOUNT_OBJECT from '@salesforce/schema/Account’;
import NAME_FIELD from '@salesforce/schema/Account.Name’;
export default class LdsCreateRecord extends LightningElement {
@track accountId;
name = ‘’;
handleNameChange(event) {
this.accountId = undefined;
this.name = event.target.value;
}
createAccount() {
const fields = {};
fields[NAME_FIELD.fieldApiName] = this.name;
const recordInput = { apiName: ACCOUNT_OBJECT.objectApiName, fields };
createRecord(recordInput) .then(account => {
this.accountId = account.id;
this.dispatchEvent(
new ShowToastEvent({
title: 'Success’,
message: 'Account created’,
variant: 'success’,
}),
);
}) .catch(error => {
this.dispatchEvent(
new ShowToastEvent({
title: 'Error creating record’,
message: error.body.message,
variant: 'error’,
}),
);
});
}
}
23. L’intéraction avec les données
L’appel aux méthodes Apex
• Nécessaire seulement si le besoin n’est pas couvert par le wire service ou les composants
standards tels que le Lightning Record Form ou les Lightning Record View Form et
Lightning Record Edit Form
• Nécessite l’import de la méthode avec la syntaxe:
• Comme pour le framework Aura, une méthode Apex se rend disponible à l’appel grâce à
l’annotation @AuraEnabled
• Il est possible de lier une propriété ou méthode Javascript à l’appel de la méthode Apex (à
condition qu’elle soit définit comme cachable) avec la syntaxe:
import apexMethodName from '@salesforce/apex/Namespace.Classname.apexMethodReference';
@wire(apexMethod, { apexMethodParams })
propertyOrFunction;
24. L’intéraction avec les données
L’appel aux méthodes Apex
• Appel d’une méthode cachable
// ContactController.cls
public with sharing class ContactController {
@AuraEnabled(cacheable=true)
public static List<Contact> getContactList() {
return [SELECT Id, Name, Title, Phone, Email, Picture__c FROM Contact WHERE Picture__c != null LIMIT 10];
}
}
Apex
// apexWireMethodToProperty.js
import { LightningElement, wire } from 'lwc’;
import getContactList from '@salesforce/apex/ContactController.getContactList;
export default class ApexWireMethodToProperty extends LightningElement {
@wire(getContactList) contacts;
}
Javascript Controller
25. L’intéraction avec les données
L’appel aux méthodes Apex
• Appel d’une méthode non cachable: pas de possibilité d’utiliser le wire service
// apexImperativeMethod.js
import { LightningElement, track } from 'lwc’;
import getContactList from '@salesforce/apex/ContactController.getContactList’;
export default class ApexImperativeMethod extends LightningElement {
@track contacts;
@track error;
handleLoad() {
getContactList()
.then(result => {
this.contacts = result;
})
.catch(error => {
this.error = error;
});
}
}
27. • Technologies fondamentalement différentes -> Analyse préalable du composant
• Aura et LWC peuvent cohabiter -> un composant Aura peut inclure un composant LWC
• Commencer par les composants les plus simples -> probablement les composants enfants
(voir notion précédente)
Stratégie
Migration Aura vers LWC
29. • Créez une nouvelle organisation Salesforce de type Developer Edition en cliquant ici:
https://developer.salesforce.com/signup
• Activez My Domain
• Activez le Dev Hub
• Dans Visual Studio Code, exécutez les commandes suivantes:
• sfdx force:auth:web:login --setdefaultdevhubusername --setalias DevHub
• Connectez vous à votre developer edition nouvellement créée
• sfdx force:project:create -n workshopLWC
• cd workshopLWC
• sfdx force:org:create -s -f config/project-scratch-def.json -a worshopLWCSScratch
Configuration de Salesforce DX
Exercice
30. • Dans Visual Studio Code:
• Ouvrez la palette de commande avec le raccourci Ctrl+Shif+P
• Exécutez SFDX: Create Lightning Web Component
• Nommez votre composant listContacts
• Utilisez la librairie de composants standards fournie par Salesforce pour développer votre
composant
• Pour rappel, le composant doit contenir un formulaire de création de contact (voir le wire service
précédemment évoqué) et une liste des contacts en base
• Le formulaire de création doit au moins contenir les champs: prénom, nom et email
• Il serait préférable d’ajouter chacune de ces fonctionnalités dans des cards différentes
Création du Lightning Web Component
Exercice
31. • Configurez le composant pour qu’il puisse être ajouté aux pages Lightning en utilisant le
code suivant dans le fichier listContact.js-meta.xml:
• Dans Visual Studio Code, une fois le code enregistré, exécutez les commandes:
• sfdx force:source:push
• sfdx force:org:open
• Ajoutez le composant créé à la page Lightning que vous souhaitez puis testez votre
composant !
Création du Lightning Web Component (suite)
Exercice
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="listContacts">
<apiVersion>45.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__AppPage</target>
<target>lightning__RecordPage</target>
<target>lightning__HomePage</target>
</targets>
</LightningComponentBundle>
32. • Le code correspondant à la correction de l’exercice est disponible sur Github à l’adresse:
https://github.com/mlezer/bordeaux-dev-group-lwc
• Pour aller plus loin, rendez-vous sur https://github.com/trailheadapps/lwc-recipes
Corrrection
Exercice