Usar o Apex para trabalhar com dados
Objetivos de aprendizagem
Após concluir esta unidade, você estará apto a:
- Reconhecer quando você precisa usar o Apex para trabalhar com os dados do Salesforce.
- Chamar o Apex de duas maneiras diferentes.
- Trabalhar com listas de registros usando o Apex e lightning-datatable.
Apex em componentes Web do Lightning
Já abordamos os benefícios do Lightning Data Service e como usá-lo, mas, às vezes, nem os componentes do lightning-record-*-form
nem os adaptadores de conexão e as funções do LDS se adequam a um caso de uso específico. Por exemplo, quando você deseja personalizar uma transação com dados de registro único ou realizar operações com vários registros em uma única transação, o Apex é a melhor opção.
Usar métodos do Apex com componentes Web do Lightning
Um método do Apex usado em um componente Web do Lightning deve ser static
, public
ou global
e anotado com @AuraEnabled
imediatamente antes da definição do método. A anotação @AuraEnabled
disponibiliza o método do Apex para componentes do Lightning (tanto componentes Web do Lightning quanto componentes do Aura).
Permitir que a estrutura armazene dados em cache elimina chamadas de servidor repetidas, fazendo com que as operações de leitura futuras executem mais rapidamente. Marcamos um método como armazenável em cache definindo cacheable = true
na anotação @AuraEnabled
. Quando um método de @AuraEnabled
pode ser armazenado em cache, as operações de linguagem de manipulação de dados (DML) não são permitidas. Na linha 2 deste exemplo, transformamos o método getContactsBornAfter
em armazenável em cache.
ContactController.cls
public with sharing class ContactController { @AuraEnabled(cacheable=true) public static List<Contact> getContactsBornAfter(Date birthDate) { return [ SELECT Name, Title, Email, Phone FROM Contact WHERE Birthdate > :birthDate WITH SECURITY_ENFORCED ]; } }
Quando um método é armazenável em cache, versões recentemente adicionadas ou alteradas de registros não podem ser retornadas até que o cache seja atualizado. Saiba como atualizar o cache manualmente na próxima seção.
Chamar métodos do Apex a partir do LWC
Existem duas maneiras de interagir com os métodos do Apex a partir de componentes Web do Lightning: conectar o método ou chamar o método imperativamente. Vamos considerar as duas abordagens.
Chamar Apex usando @wire
Para conectar um método do Apex, o método deve ser armazenável em cache. Para conectar um método do Apex armazenável em cache, use o decorador @wire
(da mesma forma que você usa um adaptador de conexão do LDS). Chamar o Apex dessa forma delega o controle para o mecanismo dos componentes Web do Lightning e cria um serviço reativo. Toda vez que o valor de um parâmetro passado para o método do Apex muda, o método Apex é executado, provisionando a propriedade ou função decorada com o novo valor. Como os métodos conectados precisam ser armazenáveis em cache, os dados podem vir do cache do LDS ou do servidor. Para atualizar os dados que foram armazenados em cache por um método do Apex, chame a função refreshApex.
Nota: o Lightning Data Service não tem conhecimento dos dados armazenados em cache por métodos do Apex. Quando uma função do LDS atualiza um registro, essa atualização não afeta os dados que foram armazenados em cache por um método do Apex.
Veja um exemplo de como usar @wire
para chamar o Apex. Este código obtém contatos que nasceram após a data de nascimento especificada.
wireApexProperty.js
import { LightningElement, api, wire } from 'lwc'; import getContactsBornAfter from '@salesforce/apex/ContactController.getContactsBornAfter'; export default class WireApexProperty extends LightningElement { @api minBirthDate; @wire(getContactsBornAfter, { birthDate: '$minBirthDate' }) contacts; }
Destaques do código:
- Linha 2: Importamos a função
getContactsBornAfter
da classe do ApexContactController
. Isso aponta para o método do Apex correspondente. - Linha 4: Definimos uma propriedade
@api minBirthDate
. Quando você usa este componente em seu código ou expõe um atributo FlexiPage, você pode passar uma data para a propriedade@api minBirthDate
. - Linha 5: O decorador
@wire
recebe dois parâmetros: o método do Apex que queremos chamar (getContactsBornAfter
) e o parâmetro que o adaptador precisa (birthDate
). Passamos$minBirthDate
como uma variável reativa (começando com$
). - Linha 6: O resultado é armazenado na propriedade
contacts
(contatos). - Linhas 5 a 6: inicialmente, o método do Apex provisiona dados para a propriedade
contacts
e armazena esses dados no cache do LDS. Como$minBirthDate
é reativa, cada vez que seu valor muda, o método do Apex executa e provisiona novos dados, seja a partir do cache ou do servidor.
Chamar Apex imperativamente
Uma alternativa a chamar o Apex com @wire
é chamar imperativamente o Apex. Chame o Apex imperativamente quando precisar controlar a invocação de operações de leitura e quando modificar registros. Para chamar o Apex de forma imperativa, invoque a função importada do arquivo JavaScript do componente. A função retorna uma promessa de JavaScript (como acontece quando você chama uma função do LDS imperativamente).
Você pode chamar tanto os métodos do Apex que podem ser armazenados em cache quanto os que não podem imperativamente. No entanto, você não pode atualizar um método do Apex armazenado em cache imperativamente. Em vez disso, chame o método usando @wire
e atualize-o com refreshApex
.
No exemplo callApexImperative.js, quando um usuário clica em um lightning-button
no arquivo .html (não mostrado), handleButtonClick
chama o método do Apex getContactsBornAfter
imperativamente.
callApexImperative.js
import { LightningElement, api, wire } from 'lwc'; import getContactsBornAfter from '@salesforce/apex/ContactController.getContactsBornAfter'; export default class CallApexImperative extends LightningElement { @api minBirthDate; handleButtonClick() { getContactsBornAfter({ //imperative Apex call birthDate: this.minBirthDate }) .then(contacts => { //code to execute if related contacts are returned successfully }) .catch(error => { //code to execute if related contacts are not returned successfully }); } }
Destaques do código:
- Linha 2: importamos a função
getContactsBornAfter
da classeContactController
. - Linha 4: Definimos uma propriedade pública
minBirthDate
para a qual você pode passar uma data ao usar este componente em seu código ou expor um atributo FlexiPage. - Linhas 6 a 7: Quando o método
handleButtonClick
é invocado pela estrutura, invocamos o método do ApexgetContactsBornAfter
imperativamente, passando abirthDate
que o método precisa para obter os contatos relacionados à data de nascimento especificada. - Linhas 9 a 14: a chamada do Apex imperativa na linha 6 retornou uma promessa. Se a chamada do método do Apex for bem-sucedida, a promessa será cumprida e o método
then
será executado. Caso contrário, a promessa será rejeitada e o métodocatch
será executado.
A maneira preferencial de trabalhar com listas de registros nos componentes Web do Lightning é usar o componente base lightning-datatable
. Use lightning-datatable
para criar tabelas de dados com recursos como rolagem infinita, edição inline, cabeçalho e ações no nível da linha, redimensionamento e muito mais. Esse componente de IU precisa ser alimentado com dados. A maneira mais comum de gerar esses dados é chamar o Apex em qualquer uma das maneiras explicadas anteriormente neste módulo.
Implantar um componente Web do Lightning que lista registros em uma tabela
Vamos trabalhar com um exemplo que exibe uma lista de contas existentes em lightning-datatable
. Usaremos o Apex e @wire
para recuperar os registros.
- Crie uma classe do Apex chamada
AccountController
:
- No painel do Explorer, clique com o botão direito na pasta classes e selecione SFDX: Criar classe do Apex.
- No nome da classe, insira
AccountController
e pressione Enter. - Pressione Enter novamente para aceitar o diretório padrão.
- Substitua o conteúdo da classe AccountController por este código:Destaques do código:
public with sharing class AccountController { @AuraEnabled(cacheable=true) public static List<Account> getAccounts() { return [ SELECT Name, AnnualRevenue, Industry FROM Account WITH SECURITY_ENFORCED ORDER BY Name ]; } }
- Linha 2: anotamos o método com
@AuraEnabled(cacheable=true)
para que os resultados sejam armazenados em cache. - Linha 3: definimos o método
getAccounts
no Apex para realizar uma operação de leitura e recuperar contas existentes.
- Crie um componente Web do Lightning chamado
accountList
. - Substitua o conteúdo de seu accountList.js por este código:Destaques do código:
import { LightningElement, wire } from 'lwc'; import NAME_FIELD from '@salesforce/schema/Account.Name'; import REVENUE_FIELD from '@salesforce/schema/Account.AnnualRevenue'; import INDUSTRY_FIELD from '@salesforce/schema/Account.Industry'; import getAccounts from '@salesforce/apex/AccountController.getAccounts'; const COLUMNS = [ { label: 'Account Name', fieldName: NAME_FIELD.fieldApiName, type: 'text' }, { label: 'Annual Revenue', fieldName: REVENUE_FIELD.fieldApiName, type: 'currency' }, { label: 'Industry', fieldName: INDUSTRY_FIELD.fieldApiName, type: 'text' } ]; export default class AccountList extends LightningElement { columns = COLUMNS; @wire(getAccounts) accounts; }
- Linhas 2 a 4: importamos referências de campo, como nos exemplos anteriores.
- Linha 5: importamos a função
getAccounts
da classe AccountController. - Linha 13: usamos
@wire
com a funçãogetAccounts
para recuperar os dados. - Linha 14: armazenamos o resultado na propriedade
accounts.data
. Se a operação for bem-sucedida, os registros podem ser acessados emaccounts.data
. Se não for, o erro aparecerá emaccounts.error
.
- Substitua o conteúdo de seu arquivo accountsList.html por este código:Destaques do código:
<template> <lightning-card> <template if:true={accounts.data}> <lightning-datatable key-field="Id" data={accounts.data} columns={columns} > </lightning-datatable> </template> </lightning-card> </template>
- Linhas 4 a 9: definimos o componente básico
lightning-datatable
para usaraccounts.data
ecolumns
que são preenchidos no arquivo JavaScript.
- Salve sua classe AccountController.
- Substitua o conteúdo de seu accountList.js-meta.xml por este código para que o componente esteja disponível nas páginas do aplicativo:
<?xml version="1.0" encoding="UTF-8"?> <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> <apiVersion>48.0</apiVersion> <isExposed>true</isExposed> <targets> <target>lightning__AppPage</target> </targets> </LightningComponentBundle>
- Salve todos os três arquivos de componente.
- Implante a pasta force-app/main/default em seu Trailhead Playground.
- Em seu Trailhead Playground, navegue até o Criador de aplicativo Lightning e abra a página Working with Data (Como trabalhar com dados).
- Arraste o componente accountList até a região principal da página.
- Salve a página.
- Volte para a página Working with Data (Como trabalhar com dados) para ver seu novo componente.
Agora você sabe algumas maneiras de interagir com os dados do Salesforce em seus componentes Web do Lightning. Em seguida, você aprenderá a lidar com erros do servidor quando eles ocorrerem.
Recursos