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
getContactsBornAfterda 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
@wirerecebe dois parâmetros: o método do Apex que queremos chamar (getContactsBornAfter) e o parâmetro que o adaptador precisa (birthDate). Passamos$minBirthDatecomo 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
contactse 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
getContactsBornAfterda classeContactController. - Linha 4: Definimos uma propriedade pública
minBirthDatepara 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 ApexgetContactsBornAfterimperativamente, passando abirthDateque 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
thenserá executado. Caso contrário, a promessa será rejeitada e o métodocatchserá 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
AccountControllere 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
getAccountsno 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
getAccountsda classe AccountController. - Linha 13: usamos
@wirecom a funçãogetAccountspara 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-datatablepara usaraccounts.dataecolumnsque 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
