Utilizar Apex para trabajar con datos
Objetivos de aprendizaje
Después de completar esta unidad, podrá:
- Reconocer cuándo necesita utilizar Apex para trabajar con datos de Salesforce.
- Llamar Apex de dos formas diferentes.
- Trabajar con listas de registros utilizando Apex y lightning-datatable.
Apex en componentes web Lightning
Tratamos las ventajas de Lightning Data Service y cómo utilizarlo, pero a veces, ni los componentes lightning-record-*-form
ni las funciones y los adaptadores de red de LDS responden a un caso de uso concreto. Por ejemplo, cuando desea personalizar una transacción de datos de un solo registro, o realizar operaciones de múltiples registros en una sola transacción, Apex es la mejor opción.
Utilizar métodos de Apex con componentes web Lightning
Un método de Apex utilizado en un componente web Lightning debe ser static
, public
o global
, y anotado con @AuraEnabled
inmediatamente antes de la definición del método. La anotación @AuraEnabled
hace que el método de Apex esté disponible en componentes Lightning (tanto componentes web Lightning como componentes Aura).
Permitir al marco de trabajo almacenar datos en caché elimina las llamadas del servidor repetidas haciendo que las operaciones de lectura futuras se ejecuten de forma más rápida. Marcamos un método como con capacidad de caché estableciendo cacheable = true
en la anotación @AuraEnabled
. Cuando un método @AuraEnabled
tiene capacidad de caché, no se permiten operaciones de Lenguaje de manipulación de datos (DML). En la línea 2 de este ejemplo, hacemos que el método getContactsBornAfter
tenga capacidad de caché.
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 ]; } }
Cuando un método tiene capacidad de caché, las versiones recién agregadas o modificadas de registros podrían no ser devueltas hasta que se actualice el caché. Obtenga información acerca de cómo actualizar manualmente el caché en la siguiente sección.
Llamar métodos de Apex desde LWC
Existen dos formas de interactuar con métodos de Apex desde componentes web Lightning: conectar el método o llamar al método de forma imperativa. Consideremos ambos enfoques.
Llamar a Apex utilizando @wire
Para conectar un método de Apex, el método debe tener capacidad de caché. Para conectar un método de Apex con capacidad de caché, utilice el decorator @wire
(del mismo modo que utiliza un adaptador de red de LDS). Llamar a Apex de este modo delega el control al motor Componentes web Lightning y crea un servicio reactivo. Cada vez que cambia el valor de un parámetro que pasó al método de Apex, se ejecuta el método de Apex y se proporciona el nuevo valor a la función o propiedad decoradas. Como los métodos conectados deben tener capacidad de caché, los datos pueden proceder del caché de LDS o el servidor. Para actualizar los datos que se almacenaron en caché por un método de Apex, llame la función refreshApex.
Nota: Lightning Data Service no está al tanto de los datos almacenados en caché por métodos de Apex. Cuando una función de LDS actualiza un registro, esa actualización no tiene ninguna repercusión en datos almacenados en caché por un método de Apex.
Este es un ejemplo del uso de @wire
para llamar a Apex. Este código obtiene contactos que nacieron después de la fecha de nacimiento 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; }
Aspectos destacados de código:
- Línea 2: importamos la función
getContactsBornAfter
desde la clase de ApexContactController
. Esto apunta al método de Apex correspondiente. - Línea 4: definimos una propiedad
@api minBirthDate
. Cuando usa este componente en su código o expone un atributo FlexiPage, puede pasar una fecha a la propiedad@api minBirthDate
. - Línea 5: el decorador
@wire
recibe dos parámetros: el Método Apex al que queremos llamar (getContactsBornAfter
) y el parámetro que el adaptador necesita (birthDate
). Pasamos$minBirthDate
como una variable reactiva (comenzando por$
). - Línea 6: el resultado se almacena en la propiedad
contacts
(contactos). - Línea 5 a 6: inicialmente, el Método Apex proporciona datos a la propiedad
contacts
(contactos) y almacena esos datos en la caché de LDS. Como$minBirthDate
es reactivo, cada vez que su valor cambia, el Método Apex ejecuta y proporciona nuevos datos, ya sea de la caché o del servidor.
Llamar Apex de forma imperativa
Una alternativa a llamar a Apex con @wire
es llamar a Apex de forma imperativa. Llame a Apex de forma imperativa cuando necesite controlar la invocación de operaciones de lectura y cuando modifique registros. Para llamar a Apex de forma imperativa, invoque la función importada desde el archivo JavaScript del componente. La función devuelve un compromiso de JavaScript (como cuando llama a una función de LDS de forma imperativa).
Puede llamar métodos de Apex tanto con capacidad de caché como sin capacidad de caché de forma imperativa. Sin embargo, no puede actualizar un método de Apex con capacidad de caché de forma imperativa. En su lugar, llame al método @wire
y actualícelo con refreshApex
.
En el ejemplo callApexImperative.js, cuando un usuario hace clic en un lightning-button
en el archivo .html (no mostrado), handleButtonClick
llama al método de Apex getContactsBornAfter
de forma imperativa.
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 }); } }
Aspectos destacados de código:
- Línea 2: importamos la función
getContactsBornAfter
desde la claseContactController
. - Línea 4: definimos una propiedad
minBirthDate
pública, a la que puede pasar una fecha mediante este componente en su código o si expone un atributo FlexiPage. - Línea 6 a 7: cuando el marco de trabajo invoca el método
handleButtonClick
, invocamos el Método ApexgetContactsBornAfter
de forma imperativa y pasamos el parámetrobirthDate
que el método necesita para obtener los contactos nacidos después de la fecha de nacimiento especificada. - Línea 9 a 14: La llamada de Apex imperativa en la línea 6 devolvió un compromiso. Si la llamada del Método Apex se realiza correctamente, el compromiso se cumple y se ejecuta el método
then
. De lo contrario, el compromiso se rechaza y se ejecuta el métodocatch
.
La forma preferida de trabajar con listas de registros en componentes web Lightning es utilizar el componente base lightning-datatable
. Utilice lightning-datatable
para crear tablas de datos con funciones como desplazamiento infinito, modificación en línea, acciones a nivel de fila y encabezado, ajuste de tamaño y mucho más. Este componente de la interfaz de usuario debe ser datos de federación. La forma más común de generar esos datos es llamar a Apex en cualquiera de las formas explicadas anteriormente en este módulo.
Implementar un componente web Lightning que enumera registros en una tabla
Trabajemos con un ejemplo que muestra una lista de cuentas existentes en lightning-datatable
. Utilizaremos Apex y @wire
para recuperar los registros.
- Cree una clase de Apex denominada
AccountController
:
- En el panel Explorador, haga clic con el botón derecho en la carpeta clases y seleccione SFDX: Crear clase de Apex.
- Para el nombre de clase, ingrese
AccountController
y pulse Enter (Intro). - Pulse Entrar de nuevo para aceptar el directorio predeterminado.
- Sustituya los contenidos de su clase AccountController con este código:Aspectos destacados de 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 ]; } }
- Línea 2: anotamos el método con
@AuraEnabled(cacheable=true)
de modo que se almacenen los resultados en la caché. - Línea 3: definimos el método
getAccounts
en Apex para realizar una operación de lectura y recuperar las cuentas existentes.
- Cree un componente web Lightning denominado
accountList
. - Sustituya los contenidos de su archivo accountList.js por el siguiente código:Aspectos destacados de 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; }
- Línea 2 a 4: Importamos referencias de campo, al igual que en los pasos anteriores.
- Línea 5: importamos la función
getAccounts
desde la clase AccountController. - Línea 13: utilizamos
@wire
con la funcióngetAccounts
para recuperar los datos. - Línea 14: almacenamos el resultado en la propiedad
accounts
(cuentas). Si la operación se realiza correctamente, se puede acceder a los registros enaccounts.data
. Si falla, el error aparece enaccounts.error
.
- Sustituya los contenidos de su archivo accountList.html por el siguiente código:Aspectos destacados de 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>
- Línea 4 a 9: definimos el componente base
lightning-datatable
para utilizaraccounts.data
ycolumns
que se rellenan en el archivo JavaScript.
- Guarde su clase AccountController.
- Sustituya los contenidos de su accountList.js-meta.xml con este código de modo que el componente esté disponible en páginas de aplicación:
<?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>
- Guarde los tres archivos de componente.
- Implemente la carpeta force-app/main/default en su Trailhead Playground.
- En su instancia de Trailhead Playground, desplácese al Generador de aplicación Lightning y abra la página Working with Data (Trabajo con los datos).
- Arrastre el componente accountList a la región principal de la página.
- Guarde la página.
- Vuelva a la página Working with Data (Trabajo con los datos) para ver su nuevo componente.
Ahora conoce algunas formas de interactuar con datos de Salesforce en sus componentes web Lightning. A continuación, obtiene información acerca de cómo gestionar errores del servidor cuando se produzcan.
Recursos