Composant Web Lightning (LWC) : Astuces et recommandations
Avis d'experts
Depuis que les composants Web Lightning sont devenus disponibles en Spring’ 19 (Février 2019), les développeurs sont plus nombreux à migrer ou créer des LWC (au lieu de développer des composants Aura) car les LWC utilisent des standards web et Javascript plus récent.
Pourquoi ?
Tous ceux qui développent des LWC ont surement beaucoup appris depuis leur premier composant et cet article a pour objectif de donner quelques astuces et recommandations.
Pour qui ?
Cet article s’adresse à des profils techniques et tous ceux qui ont déjà développé ou développent activement des LWC ; Développeur(se) Salesforce, Tech Lead, Architect
Recommandations
Nous avons sélectionné quelques recommandations à prendre en considération lorsque vous développez des composants Web Lightning.
connectedCallback v/s getters et setters
Utiliser la fonction connectedCallback pour effectuer une initialisation de donnée, écouter des événements or récupérer des données.
Cependant, une fonction de type getter/setter est plus appropriée si vous avez besoin d’exécuter une logique spécifique à chaque modification d’une variable ; ce qui signifie que connectedCallback n’est pas recommandé dans ce cas car il s’exécute qu’une seule fois au chargement du composant.
//Gets executed only once connectedCallback() { this.username = this.username.trim(); } //Gets re-evaluated each time the property value changes @api get userName() { return this.username; } set userName(value) { this.username= value.trim(); }
|
Générer plusieurs templates HTML
Il est possible d’utiliser plusieurs fichier templates (html) pour un même composant Web Lightning, par exemple, si on a besoin d’afficher une page pour la version mobile et une autre pour la version desktop :
- Créer un fichier HTML spécifique pour chaque version d’écran
- Importer les fichiers HTMP dans le fichier Javascript du composant (component.js)
import {default as desktopTemplate } from './multipleTemplatesDemo.html' import {default as mobileTemplate } from './multipleTemplatesDemoMobile.html'
- Importer la propriété formFactor
import formFactorPropertyName from '@salesforce/client/formFactor';
- Définir une méthode “render” pour contrôler l’affichage de la bonne page HTML en fonction de la variable formFactorPropertyName
render() { return formFactorPropertyName === "Small"? mobileTemplate :
desktopTemplate; }
Réutiliser un module Javascript dans d’autres composants
Si l’environnement Salesforce est multilingue, il est important de considérer la langue de l’utilisateur connecté lorsqu’on développe un composant web Lightning.
Quand on parle de traduction, on pense tout de suite aux étiquettes personnalisées.
Mais comment faire si on a besoin de référencer les mêmes étiquettes personnalisées dans plusieurs LWC sans dupliquer les références dans chaque composant.
Le plus simple c’est de créer un composant LWC de type « bibliothèque ».
Ce composant contient le fichier metadata XML et le fichier javascript (genGlobalAssets.js) avec les « imports » des étiquettes personnalisées.
Ajouter toutes les lignes d’import des étiquettes personnalisées et terminer par une ligne d’export pour ce composant puisse être importer.
//genGlobalAssets.js import Label1 from '@salesforce/label/c.Label1; import Label2 from '@salesforce/label/c.Label1; import Label3 from '@salesforce/label/c.Label1; //add further labels and include in the object to be exported
const label = { Label1, Label2, Label3 }
export{label};
Ensuite, il suffit d’importer ce composant en tant que module dans tous les autres LWC qui en ont besoin.
//lwcYourComponent.js
import {label} from 'c/genGlobalAssets; export default class LwcYourComponent extends LightningElement {
label1 = label.Label1; //local variable storing label value customFunction() { console.log(this.label1); // access the local variable from any function }
}
L’avantage de cette solution c’est la flexibilité d’ajouter une nouvelle étiquette personnalisée uniquement dans le composant « bibliothèque » et le propager sur les autres sans avoir à modifier les autres composants qui ont besoin de cette étiquette.
Usage de “wire pageReference”
Intégrer un composant web Lightning dans une page Lightning peut causer des problèmes de cache sur le navigateur avec l’affichage des données obsolètes.
Pour résoudre ceci, il est recommandé d’utiliser @wire(CurrentPageReference) et getter/setter méthodes au lieu de connectedCallback.
Voir la documentation Salesforce ici :
The connectedCallback() hook is invoked with the initial properties passed to the component. If a component derives its internal state from the properties, it’s better to write the logic in a setter than in connectedCallback()
@wire(CurrentPageReference) collecte la nouvelle valeur d’une variable à chaque fois que la page se charge, ce qui permet d’appeler une logique spécifique lors de la mise à jour de cette variable.
Pour illustrer le fonctionnement de @wire(CurrentPageReference), voici un exemple comment naviguer vers un composant web Lightning qui se trouve dans une page Lightning, ainsi éliminer le problème de cache.
- Importer NavigationMixin et CurrentPageReference dans le composant
import { NavigationMixin } from 'lightning/navigation'; import { CurrentPageReference } from 'lightning/navigation';
- Referencer NavigationMixin
export default class TestLWC extends NavigationMixin(LightningElement) {
- Si besoin, stocker les parametres qui passent dans PageReference (dans cet exemple on stock le recordId)
@wire(CurrentPageReference) getStateParameters(currentPageReference) { if (currentPageReference) { this.recordId = currentPageReference.state.recordId; navigateToLWCPage() } }
- Logique de navigation vers le composant web Lightning
this[NavigationMixin.Navigate]({ type: 'standard__navItemPage', attributes: { apiName: 'API_Name_App_Page' // api name of the Lightning App Page }, state: { c__yourRecordId : this.recordId //passing parameters to the pageReference } });
VOICI LE CODE POUR L’UTILISATION DE PAGEREFERENCE
LWC component tab
HTML
<template> <div class="slds-grid slds-theme_default slds-box"> <div class="slds-col slds-size_4-of-12"> <h2 class="slds-text-heading_small slds-var-m-bottom_medium"> Load Id : <code> {loadId}</code> </h2> </div> <div class="slds-col slds-size_8-of-12" if:true={objectApiName}> <lightning-record-view-form object-api-name={objectApiName} record-id={loadId}> <div class="slds-box"> <lightning-output-field field-name="Name"> </lightning-output-field> </div> </lightning-record-view-form> </div> </div> </template>
JS
import { LightningElement,api, wire, track } from 'lwc'; import { CurrentPageReference, NavigationMixin } from 'lightning/navigation'; export default class LwcCustomTab extends NavigationMixin(LightningElement) { currentPageReference; @api loadId; @api objectApiName; @wire(CurrentPageReference) getCurrentPageReference(currentPageReference) { this.currentPageReference = currentPageReference; //show spinner if processing is long new Promise( (resolve, reject) => { setTimeout(() => { if(this.currentPageReference){ this.loadId = this.currentPageReference.state.c__loadId ? this.currentPageReference.state.c__loadId : null; this.objectApiName = this.currentPageReference.state.c__objectApiName ? this.currentPageReference.state.c__objectApiName : null; //perform additional logic with new loadId resolve(); } }, 0); }) .catch((error) => { console.error(JSON.stringify(error)); }) .finally(() => { // disable a spinner if applicable }); } }
XML File
<?xml version="1.0" encoding="UTF-8"?> <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> <apiVersion>53.0</apiVersion> <isExposed>true</isExposed> <targets> <target>lightning__Tab</target> </targets> </LightningComponentBundle>
Redirection vers onglet spécifique
HTML
<template> <div class="slds-grid slds-theme_default slds-box"> <div class="slds-col"></div> <div class="slds-col"> <lightning-button label="Redirect To Tab" variant="brand" onclick={navigateToCustomTab} ></lightning-button> </div> </div> </template>
JS
import { LightningElement, api } from 'lwc'; import { NavigationMixin } from 'lightning/navigation'; export default class LwcNavigateToTab extends NavigationMixin(LightningElement) { @api loadId; @api recordId; @api objectApiName; navigateToCustomTab(){ this[NavigationMixin.Navigate]({ type: 'standard__navItemPage', attributes: { apiName: 'LWC_Custom_Tab' }, state: { c__loadId : this.recordId ? this.recordId : this.loadId, c__objectApiName : this.objectApiName } }); } }
XML file
<?xml version="1.0" encoding="UTF-8"?> <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> <apiVersion>53.0</apiVersion> <isExposed>true</isExposed> <targets> <target>lightning__RecordPage</target> <target>lightning__AppPage</target> <target>lightning__HomePage</target> </targets> <targetConfigs> <targetConfig targets="lightning__RecordPage,lightning__AppPage,lightning__HomePage"> <property name="loadId" label="Custom Load Id" type="String" /> <property name="objectApiName" label="Object API Name" type="String" /> </targetConfig> </targetConfigs> </LightningComponentBundle>
Auteurs
Shamina Mossodeea, Senior Manager Comforth Easyfront