Trabalhar com listas de registros
Criar o componente de lista de ursos
Os guardas florestais querem ver um diretório de ursos diretamente na página inicial. Você recebeu a tarefa de implementar essa lista de ursos.
- No VS Code, clique com o botão direito do mouse na pasta
lwc
e clique em SFDX: Create Lightning Web Component (Criar componente Web do Lightning). - Dê ao componente o nome
bearList
. - Edite o arquivo
bearList.js-meta.xml
e substitua<isExposed>false</isExposed>
por estas linhas.<isExposed>true</isExposed> <targets> <target>lightning__AppPage</target> <target>lightning__RecordPage</target> <target>lightning__HomePage</target> </targets>
Isso permite que seu componente seja colocado em qualquer tipo de página no Criador de aplicativo Lightning. - Substitua o conteúdo 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>
Destaques do código:- A marca
template
com as diretivasfor:each
efor:item
é usada para iterar pelos registros debears
. Cada item da iteração é transmitido à propriedadebear
. - Cada iteração do modelo é marcada com um atributo
key
especial.key
precisa ter um valor exclusivo no contexto da iteração. Esse valor é a ID de urso no nosso componente.
- A marca
- Substitua o conteúdo 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; }); } }
Destaques do código:- Importamos o adaptador
ursusResources
, que nos dá acesso a um recurso estático associado ao nosso aplicativo. Usamos esse adaptador para criar um objetoappResources
que expõe a URL de imagem de silhueta do urso no modelo. - Importamos o adaptador
getAllBears
, que nos permite interagir com o método do ApexBearController.getAllBears()
. A classeBearController
fica junto do código que você implantou no início desse projeto. O métodogetAllBears
retorna o resultado de uma consulta que busca todos os registros de ursos. - Implementamos a função
connectedCallback
, que nos permite executar código depois que o componente é carregado. Usamos essa função para chamar a funçãoloadBears
. - A função
loadBears
chama o adaptadorgetAllBears
. O adaptador chama nosso código do Apex e retorna uma promessa de JS. Usamos a promessa para salvar os dados retornados na propriedadebears
ou para relatar erros. A recuperação de dados com essa abordagem é chamada de Apex imperativo.
- Importamos o adaptador
- Crie outro arquivo
bearList.css
no diretóriobearList
e cole o seguinte código no arquivo..bear-tile { display: block; border: 1px solid #d2955d; border-radius: .25rem; background-color: #fae8d2; } .bear-silhouette { height: 100px; }
Essas regras de CSS adicionam uma borda aos cartões de urso e definem a altura de uma imagem de silhueta de urso. - Implante o código atualizado na organização. Clique com o botão direito do mouse na pasta padrão e clique em SFDX: Deploy Source to Org (Implantar fonte na organização).
Adicionar o componente de lista de ursos à página inicial do aplicativo
Vamos adicionar nosso novo componente à página inicial do aplicativo.
- De volta à organização, no App Launcher (Iniciador de aplicativos) (), encontre e selecione Ursus Park.
- Clique em Setup (Configuração) () e selecione Edit Page (Editar página).
- Em Custom Components (Componentes personalizados), encontre seu componente bearList e arraste-o para o canto superior esquerdo da página.
- Clique em Save (Salvar) e em Back (Voltar) para retornar à página inicial e verificar seu trabalho.
Usar Apex conectado
Agora vamos explorar uma nova abordagem para recuperar a lista de ursos. Vamos usar Apex conectado em vez de Apex imperativo.
- Edite
bearList.html
e substitua<template if:true={bears}>
por<template if:true={bears.data}>
. - Substitua
<template for:each={bears} for:item="bear">
por<template for:each={bears.data} for:item="bear">
. - Substitua
<template if:true={error}>
por<template if:true={bears.error}>
. Aqui, o modelo é basicamente o mesmo do Apex imperativo. Agora vamos acessar a lista de ursos chamandobears.data
em vez de somentebears
, e estamos recuperando erros combears.error
em vez de somenteerror
. - Substitua o conteúdo 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 bastante o código JS decorando nossa propriedadebears
com Apex conectado. Todos os dados de que precisamos agora vêm por essa única linha:@wire(getAllBears) bears;
- Implante o código atualizado na organização e veja se ele se comporta da mesma forma que no Apex imperativo.
Transmitir parâmetros em suas chamadas do Apex
O número de habitantes do Ursus Park está aumentando. Os guardas querem poder filtrar a lista de ursos para encontrá-los rapidamente. Vamos adicionar uma barra de pesquisa à nossa lista de ursos para ajudá-los.
- Edite
bearList.html
e adicione o código a seguir após a marca<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>
Isso adiciona um campo de entrada de pesquisa. Quando seu valor muda, chamamos a funçãohandleSearchTermChange
. - Adicione o código a seguir depois da marca de fechamento
</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>
Isso adiciona uma mensagem que indica que nenhum resultado foi encontrado. Essa mensagem é mostrada apenas quando a expressãohasResults
é falsa. - Substitua o conteúdo 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); } }
Destaques do código:- Adicionamos uma propriedade reativa
searchTerm
e a transmitimos como um parâmetro de nossa chamada de Apex conectado asearchBears
. - A função
handleSearchTermChange
é usada para reagir a mudanças no valor do campo de entrada de pesquisa. Colocamos de propósito um atraso de 300 milissegundos na atualização da propriedade reativasearchTerm
. Se houver uma atualização pendente, nós a cancelamos e reagendamos outra em 300 ms. Esse atraso reduz o número de chamadas do Apex quando o usuário está digitando letras para formar uma palavra. Cada nova letra aciona uma chamada parahandleSearchTermChange
, mas o ideal é quesearchBears
seja chamado somente uma vez quando o usuário termina de digitar. Essa técnica se chama debouncing. - Expomos a expressão
hasResults
para verificar se nossa pesquisa retornou ursos.
- Adicionamos uma propriedade reativa
- Implante o código atualizado na organização e verifique se a pesquisa funciona com ou sem resultados.
É tudo para esta etapa. Vimos como lidar com listas de registros com Apex imperativo e, depois, com Apex conectado, e aprendemos a transmitir parâmetros em nossas chamadas do Apex. O código de nosso componente cresceu bastante nesse processo, ou seja, vamos desmembrá-lo em subcomponentes para facilitar sua manutenção.