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 lwce clique em SFDX: Create Lightning Web Component (Criar componente Web do Lightning).
- Dê ao componente o nome bearList.
- Edite o arquivo bearList.js-meta.xmle 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.htmlpor:<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 templatecom as diretivasfor:eachefor:itemé usada para iterar pelos registros debears. Cada item da iteração é transmitido à propriedadebear.
- Cada iteração do modelo é marcada com um atributo keyespecial.keyprecisa 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.jspor: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 objetoappResourcesque 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 classeBearControllerfica junto do código que você implantou no início desse projeto. O métodogetAllBearsretorna 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 loadBearschama 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 propriedadebearsou para relatar erros. A recuperação de dados com essa abordagem é chamada de Apex imperativo.
 
- Importamos o adaptador 
- Crie outro arquivo bearList.cssno diretóriobearListe 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. ), encontre e selecione Ursus Park.
- Clique em Setup (Configuração) ( ) e selecione Edit Page (Editar página). ) 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.htmle 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.dataem vez de somentebears, e estamos recuperando erros combears.errorem vez de somenteerror.
- Substitua o conteúdo de bearList.jspor: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 propriedadebearscom 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.htmle 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.jspor: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 searchTerme 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 é quesearchBearsseja chamado somente uma vez quando o usuário termina de digitar. Essa técnica se chama debouncing.
- Expomos a expressão hasResultspara 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.
