Trabajar con listas de registros
Cómo crear el componente Bear List (Lista de osos)
Los guardaparques quieren ver el directorio de osos directamente desde la página de inicio. Se le asignó la tarea de implementar esa lista de osos.
- En VS Code, haga clic con el botón secundario en la carpeta
lwc
y, luego, en SFDX: Create Lightning Web Component (Crear componente web Lightning). - Asigne el nombre
bearList
al componente. - Modifique el archivo
bearList.js-meta.xml
y sustituya<isExposed>false</isExposed>
por estas líneas.<isExposed>true</isExposed> <targets> <target>lightning__AppPage</target> <target>lightning__RecordPage</target> <target>lightning__HomePage</target> </targets>
Así podrá ubicar su componente en cualquier tipo de página en el Generador de aplicación Lightning. - Sustituya el contenido de
bearList.html
por:<template> <lightning-card title="Bears" icon-name="utility:animal_and_nature"> <div class="slds-card__body slds-card__body_inner"> <!-- Start bear list --> <template if:true={bears}> <lightning-layout multiple-rows="true" pull-to-boundary="small"> <template for:each={bears} for:item="bear"> <lightning-layout-item key={bear.Id} size="3" class="slds-var-p-around_x-small"> <!-- Start bear tile --> <lightning-card title={bear.Name} class="bear-tile"> <div class="slds-var-p-horizontal_small bear-tile-body"> <div class="slds-media"> <div class="slds-media__figure"> <img src={appResources.bearSilhouette} alt="Bear profile" class="bear-silhouette"/> </div> <div class="slds-media__body"> <p class="slds-var-m-bottom_xx-small">{bear.Sex__c}</p> <p class="slds-var-m-bottom_xx-small">{bear.Age__c} years old</p> <p class="slds-var-m-bottom_xx-small">{bear.Height__c} cm</p> <p class="slds-var-m-bottom_xx-small">{bear.Weight__c} Kg</p> </div> </div> </div> </lightning-card> <!-- End bear tile --> </lightning-layout-item> </template> </lightning-layout> </template> <!-- End bear list --> <!-- Data failed to load --> <template if:true={error}> <div class="slds-text-color_error"> An error occurred while loading the bear list </div> </template> </div> </lightning-card> </template>
Aspectos destacados del código:- La etiqueta
template
(plantilla) con las directivasfor:each
yfor:item
se utiliza para iterar los registrosbears
(osos). Cada elemento de iteración se transfiere a la propiedadbear
. - Cada iteración de la plantilla se marca con un atributo
key
(clave) especial.key
debe tener un valor único en el contexto de la iteración. Este es el Id. de cada oso en nuestro componente.
- La etiqueta
- Sustituya el contenido de
bearList.js
por:import { LightningElement } from 'lwc'; import ursusResources from '@salesforce/resourceUrl/ursus_park'; /** BearController.getAllBears() Apex method */ import getAllBears from '@salesforce/apex/BearController.getAllBears'; export default class BearList extends LightningElement { bears; error; appResources = { bearSilhouette: `${ursusResources}/standing-bear-silhouette.png`, }; connectedCallback() { this.loadBears(); } loadBears() { getAllBears() .then(result => { this.bears = result; }) .catch(error => { this.error = error; }); } }
Aspectos destacados del código:- Importamos el adaptador
ursusResources
, que nos da acceso a un recurso estático asociado a nuestra aplicación. Utilizamos este adaptador para crear un objetoappResources
que expone la dirección URL de imagen con la silueta de un oso en la plantilla. - Importamos el adaptador
getAllBears
, que nos permite interactuar con el método ApexBearController.getAllBears()
. La claseBearController
se agrupa en el código que implementó al comienzo de este proyecto. El métodogetAllBears
muestra el resultado de una consulta que recupera todos los registros Bear (Oso). - Implementamos la función
connectedCallback
, que nos permite ejecutar el código después de cargar el componente. Utilizamos esta función para llamar a la funciónloadBears
. - La función
loadBears
llama al adaptadorgetAllBears
. El adaptador llama a nuestro código Apex y muestra una promesa de JS. Utilizamos la promesa para guardar los datos obtenidos en la propiedadbears
o para reportar errores. La recuperación de datos con este método se denomina Apex imperativo.
- Importamos el adaptador
- Cree un nuevo archivo
bearList.css
en el directoriobearList
y pegue el siguiente código en el archivo..bear-tile { display: block; border: 1px solid #d2955d; border-radius: .25rem; background-color: #fae8d2; } .bear-silhouette { height: 100px; }
Estas reglas de CSS agregan bordes a nuestras tarjetas de osos y establecen la altura de la imagen con la silueta de un oso. - Implemente el código actualizado en la organización. Haga clic con el botón secundario en la carpeta default (predeterminada) y, luego, en SFDX: Deploy Source to Org (Implementar fuente en organización).
Cómo agregar el componente Bear List (Lista de osos) a la página de inicio de la aplicación
Vamos a agregar el nuevo componente a la página de inicio de la aplicación.
- En su organización, desde el Iniciador de aplicación (), busque y seleccione Ursus Park.
- Haga clic en Setup (Configuración) () y seleccione Edit Page (Modificar página).
- En Custom Components (Componentes personalizados), busque el componente bearList y arrástrelo a la esquina superior izquierda de la página.
- Haga clic en Save (Guardar) y luego en Back (Atrás) para volver a la página de inicio y revisar su trabajo.
Utilizar Apex conectado
Ahora, vamos a explorar una nueva forma de recuperar la lista de osos. Utilizaremos Apex conectado en lugar de Apex imperativo.
- Modifique
bearList.html
y reemplace<template if:true={bears}>
por<template if:true={bears.data}>
. - Reemplace
<template for:each={bears} for:item="bear">
por<template for:each={bears.data} for:item="bear">
. - Reemplace
<template if:true={error}>
por<template if:true={bears.error}>
. En este punto, la plantilla es casi igual a la de Apex imperativo. Ahora accedemos a la lista de osos mediante una llamada abears.data
en lugar de solo abears
y también recuperamos errores conbears.error
en lugar de solo conerror
. - Sustituya el contenido de
bearList.js
por:import { LightningElement, wire } from 'lwc'; import ursusResources from '@salesforce/resourceUrl/ursus_park'; /** BearController.getAllBears() Apex method */ import getAllBears from '@salesforce/apex/BearController.getAllBears'; export default class BearList extends LightningElement { @wire(getAllBears) bears; appResources = { bearSilhouette: `${ursusResources}/standing-bear-silhouette.png`, }; }
Simplificamos significativamente el código JS al decorar nuestra propiedadbears
con Apex conectado. Toda la información que necesitamos ahora proviene de esta única línea:@wire(getAllBears) bears;
- Implemente el código actualizado en la organización y observe que se comporta de la misma forma que con Apex imperativo.
Especificar parámetros en las llamadas de Apex
La cantidad de habitantes en Ursus Park está aumentando. Los guardaparques desean poder filtrar la lista de osos para buscarlos rápidamente. Agreguemos una barra de búsqueda a nuestra lista de osos para ayudarlos.
- Modifique
bearList.html
y agregue el siguiente código después de la etiqueta<template if:true={bears.data}>
.<lightning-input type="search" onchange={handleSearchTermChange} variant="label-hidden" class="slds-var-m-bottom_small" label="Search" placeholder="Search for bears" value={searchTerm}> </lightning-input>
Se agregará un campo de entrada de búsqueda. Cuando el valor cambia, llamamos a la funciónhandleSearchTermChange
. - Agregue el siguiente código tras la etiqueta de cierre
</lightning-layout>
.<!-- No bears found --> <template if:false={hasResults}> <div class="slds-align_absolute-center slds-var-m-vertical_small"> This is beary disturbing, we did not find results... </div> </template>
Se agregará un mensaje que indica que no se encontraron resultados. Este mensaje solo se muestra cuando la expresiónhasResults
es falsa. - Sustituya el contenido de
bearList.js
por:import { LightningElement, wire } from 'lwc'; import ursusResources from '@salesforce/resourceUrl/ursus_park'; /** BearController.searchBears(searchTerm) Apex method */ import searchBears from '@salesforce/apex/BearController.searchBears'; export default class BearList extends LightningElement { searchTerm = ''; @wire(searchBears, {searchTerm: '$searchTerm'}) bears; appResources = { bearSilhouette: `${ursusResources}/standing-bear-silhouette.png`, }; handleSearchTermChange(event) { // Debouncing this method: do not update the reactive property as // long as this function is being called within a delay of 300 ms. // This is to avoid a very large number of Apex method calls. window.clearTimeout(this.delayTimeout); const searchTerm = event.target.value; // eslint-disable-next-line @lwc/lwc/no-async-operation this.delayTimeout = setTimeout(() => { this.searchTerm = searchTerm; }, 300); } get hasResults() { return (this.bears.data.length > 0); } }
Aspectos destacados del código:- Agregamos una propiedad reactiva
searchTerm
y la especificamos como un parámetro de nuestra llamada de Apex conectado ensearchBears
. - La función
handleSearchTermChange
se utiliza para reaccionar a cambios en el valor del campo de entrada de búsqueda. Introducimos intencionalmente una demora de 300 milisegundos cuando actualizamos la propiedad reactivasearchTerm
. Si una actualización está pendiente, la cancelamos y volvemos a programar una nueva en 300 ms. Esta demora reduce la cantidad de llamadas de Apex cuando el usuario está escribiendo las letras para formar una palabra. Cada nueva letra desencadena una llamada ahandleSearchTermChange
, pero, idealmente, solo se llama asearchBears
cuando el usuario termina de escribir. Esta técnica se denomina debouncing. - Exponemos la expresión
hasResults
para comprobar si nuestra búsqueda nos muestra osos.
- Agregamos una propiedad reactiva
- Implemente el código actualizado en la organización y compruebe que la búsqueda funcione con o sin resultados.
Así finaliza este paso. Vimos cómo gestionar listas de registros con Apex imperativo y luego con Apex conectado, y aprendimos cómo especificar parámetros en nuestras llamadas de Apex. El código de nuestro componente creció de manera significativa en el proceso, así que, ahora, vamos a dividirlo en subcomponentes para que sea más fácil de mantener.