Verwenden von Apex für die Arbeit mit Daten
Lernziele
Nachdem Sie diese Lektion abgeschlossen haben, sind Sie in der Lage, die folgenden Aufgaben auszuführen:
- Erkennen, wann Sie Apex verwenden müssen, um mit Salesforce-Daten zu arbeiten
- Aufrufen von Apex auf zwei unterschiedliche Weisen
- Arbeiten mit Datensatzlisten unter Verwendung von Apex und "lightning-datatable"
Apex in Lightning-Webkomponenten
Wir haben nun bereits die Vorteile von Lightning Data Service und seine Verwendung behandelt, doch in manchen Anwendungsfällen sind weder die lightning-record-*-form
-Komponenten noch die Wire-Adapter und -Funktionen geeignet. Wenn Sie beispielsweise eine Transaktion mit Daten aus einem Einzeldatensatz anpassen oder Vorgänge mit mehreren Datensätzen für eine Einzeltransaktion durchführen möchten, ist Apex die beste Wahl.
Verwenden von Apex-Methoden mit Lightning-Webkomponenten
Eine Apex-Methode, die in einer Lightning-Webkomponente verwendet wird, muss als static
, public
oder global
definiert und direkt vor der Methodendefinition mit der Anmerkung @AuraEnabled
versehen sein. Durch die Anmerkung @AuraEnabled
wird die Apex-Methode für Lightning-Komponenten verfügbar (sowohl Lightning-Webkomponenten als auch Aura-Komponenten).
Wenn wir zulassen, dass das Framework Daten im Cache speichert, vermeiden wir damit wiederholte Serveraufrufe und beschleunigen künftige Lesevorgänge. Wir aktivieren Caching für eine Methode, indem wir cacheable = true
in der Anmerkung @AuraEnabled
angeben. Wird eine @AuraEnabled
-Methode als cache-fähig festgelegt, sind DML-Vorgänge (Data Manipulation Language) nicht zulässig. In Zeile 2 dieses Beispiels legen wir die Methode getContactsBornAfter
als cache-fähig fest.
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 ]; } }
Wenn eine Methode cache-fähig ist, werden neu hinzugefügte oder geänderte Versionen von Datensätzen möglicherweise erst dann zurückgegeben, nachdem der Cache aktualisiert wurde. Im nächsten Abschnitt erfahren Sie, wie Sie den Cache manuell aktualisieren können.
Aufrufen von Apex-Methoden aus Lightning-Webkomponente
Es gibt zwei Möglichkeiten für die Interaktion mit Apex-Methoden innerhalb von Lightning-Webkomponenten: Man kann die Methode mit @wire verbinden oder sie imperativ aufrufen. Sehen wir uns beide Vorgehensweisen an.
Aufrufen von Apex mit @wire
Damit eine Apex-Methode mit @wire verbunden werden kann, muss sie zwischengespeichert werden können. Zum Verbinden einer als cache-fähig definierten Apex-Methode mit @wire verwenden wir den Decorator @wire
(wie bei der Verwendung eines LDS-Wire-Adapters). Bei dieser Art des Apex-Aufrufs werden die Kontrolle an die Engine von Lightning-Webkomponenten übergeben und ein reaktiver Service erstellt. Jedes Mal, wenn sich der Wert eines Parameters ändert, der an die Apex-Methode übergeben wird, wird die Apex-Methode ausgeführt, die den neuen Wert für die mit dem Decorator versehene Eigenschaft oder Funktion bereitstellt. Da mit @wire verbundene Methoden als cacheable festgelegt sein müssen, können Daten aus dem LDS-Cache oder vom Server stammen. Zum Aktualisieren der Daten, die eine Apex-Methode im Cache zwischengespeichert hat, rufen Sie die Funktion refreshApex auf.
Hinweis: Für Lightning Data Service sind die Daten, die von Apex-Methoden in den Cache geschrieben werden, nicht sichtbar. Wenn eine LDS-Funktion einen Datensatz aktualisiert, hat diese Aktualisierung keine Auswirkungen auf die Daten, die von einer Apex-Methode in den Cache geschrieben wurden.
Im folgenden Beispiel verwenden wir @wire
zum Aufrufen von Apex. Dieser Code ruft Kontakte ab, die nach dem angegebenen Geburtsdatum geboren wurden.
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; }
Code-Highlights:
- Zeile 2: Wir importieren die Funktion
getContactsBornAfter
aus der Apex-KlasseContactController
. Dies ist ein Verweis auf die zugehörige Apex-Methode. - Zeile 4: Wir definieren die Eigenschaft
@api minBirthDate
. Wenn Sie diese Komponente in Ihrem Code verwenden oder ein FlexiPage-Attribut verfügbar machen, können Sie ein Datum an die Eigenschaft@api minBirthDate
übergeben. - Zeile 5: Der Decorator
@wire
empfängt zwei Parameter: die Apex-Methode, die wir aufrufen möchten (getContactsBornAfter
), und den Parameter, den der Adapter benötigt (birthDate
). Wir übergeben$minBirthDate
als reaktive Variable (mit$
beginnend). - Zeile 6: Das Ergebnis wird in der Eigenschaft
contacts
gespeichert. - Zeilen 5–6: Zuerst stellt die Apex-Methode Daten für die Eigenschaft
contacts
bereit und speichert Daten im LDS-Cache. Da$minBirthDate
reaktiv ist, wird jedes Mal, wenn sich der Wert ändert, die Apex-Methode ausgeführt, die neue Daten entweder aus dem Cache oder vom Server bereitstellt.
Imperatives Aufrufen von Apex
Eine Alternative zum Aufrufen von Apex mit @wire
ist das imperative Aufrufen von Apex. Rufen Sie Apex imperativ auf, wenn Sie den Aufruf von Lesevorgängen steuern und Datensätze ändern müssen. Um Apex imperativ aufzurufen, rufen Sie die importierte Funktion in der JavaScript-Datei der Komponente auf. Die Funktion gibt ein JavaScript-Versprechen zurück (genau wie beim imperativen Aufruf einer LDS-Funktion).
Sie können sowohl cache-fähige als auch nicht cache-fähige Apex-Methoden zwingend aufrufen. Allerdings können Sie eine cache-fähige Apex-Methode nicht imperativ aktualisieren. Rufen Sie die Methode stattdessen mit @wire
auf und aktualisieren Sie sie mit refreshApex
.
Im Beispiel "callApexImperative.js" gilt: Wenn ein Benutzer auf eine Lightning-Schaltfläche (lightning-button
) in der HTML-Datei klickt (nicht zu sehen), ruft handleButtonClick
die Apex-Methode getContactsBornAfter
imperativ auf.
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 }); } }
Code-Highlights:
- Zeile 2: Wir importieren die Funktion
getContactsBornAfter
aus der KlasseContactController
. - Zeile 4: Wir definieren die öffentliche Eigenschaft
minBirthDate
, an die Sie ein Datum übergeben können, wenn Sie diese Komponente in Ihrem Code verwenden oder ein FlexiPage-Attribut verfügbar machen. - Zeilen 6- 7: Wenn die Methode
handleButtonClick
vom Framework aufgerufen wird, rufen wir imperativ die Apex-MethodegetContactsBornAfter
auf und übergeben das ElementbirthDate
, das die Methode benötigt, um Kontakte abzurufen, die nach dem angegebenen Geburtsdatum geboren wurden. - Zeilen 9–14: Der imperative Apex-Aufruf aus Zeile 6 gab ein Versprechen zurück. Wird der Apex-Methodenaufruf erfolgreich ausgeführt, ist das Versprechen erfüllt und die
then
-Methode wird ausgeführt. Andernfalls wird das Versprechen abgelehnt, und die Methodecatch
wird ausgeführt.
Die bevorzugte Möglichkeit für die Arbeit mit Datensatzlisten in Lightning-Webkomponenten ist die Verwendung der Basiskomponente lightning-datatable
. Verwenden Sie lightning-datatable
zum Erstellen von Datentabellen mit Funktionen wie unendlichem Bildlauf, Kopfzeilenaktionen und Aktionen auf Zeilenebene, Größenänderung usw. Diese Benutzeroberflächenkomponente muss mit Daten "gefüttert" werden. Die gängigste Methode zum Generieren dieser Daten besteht darin, Apex mit einem der Verfahren aufzurufen, die zuvor in diesem Modul erläutert wurden.
Bereitstellen einer Lightning-Webkomponente, die Datensätze in einer Tabelle auflistet
Gehen wir nun ein Beispiel durch, das eine Liste vorhandener Accounts in einer lightning-datatable
anzeigt. Wir verwenden Apex und @wire
zum Abrufen der Datensätze.
- Erstellen Sie eine Apex-Klasse namens
AccountController
:
- Klicken Sie im Fensterbereich "Explorer" mit der rechten Maustaste auf den Ordner classes und wählen Sie SFDX: Create Apex Class aus.
- Geben Sie als Klassenname
AccountController
ein und drücken Sie die Eingabetaste. - Drücken Sie erneut die Eingabetaste, um das Standardverzeichnis zu übernehmen.
- Ersetzen Sie den Inhalt der AccountController-Klasse durch diesen Code:Code-Highlights:
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 ]; } }
- Zeile 2: Wir versehen die Methode mit der Anmerkung
@AuraEnabled(cacheable=true)
, damit die Ergebnisse im Cache zwischengespeichert werden. - Zeile 3: Wir definieren die Methode
getAccounts
in Apex, um einen Lesevorgang durchzuführen und vorhandene Accounts abzurufen.
- Erstellen Sie eine Lightning-Webkomponente namens
accountList
. - Ersetzen Sie den Inhalt Ihrer Datei "accountList.js" durch diesen Code:Code-Highlights:
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; }
- Zeilen 2–4: Genau wie in den vorherigen Beispielen, importieren wir Feldverweise.
- Zeile 5: Wir importieren die Funktion
getAccounts
aus der AccountController-Klasse. - Zeile 13: Wir verwenden
@wire
mit der FunktiongetAccounts
, um die Daten abzurufen. - Zeile 14: Wir speichern das Ergebnis in der Eigenschaft
accounts
. Wird der Vorgang erfolgreich durchgeführt, stehen die Daten inaccounts.data
zum Zugriff zur Verfügung. Schlägt der Vorgang fehl, wird der Fehler inaccounts.error
geschrieben.
- Ersetzen Sie den Inhalt Ihrer Datei "accountList.html" durch diesen Code:Code-Highlights:
<template> <lightning-card> <template if:true={accounts.data}> <lightning-datatable key-field="Id" data={accounts.data} columns={columns} > </lightning-datatable> </template> </lightning-card> </template>
- Zeilen 4–9: Wir definieren die Basiskomponente
lightning-datatable
so, dass sieaccounts.data
undcolumns
verwendet, die in der JavaScript-Datei mit Daten gefüllt werden.
- Speichern Sie Ihre AccountController-Klasse.
- Ersetzen Sie den Inhalt Ihrer Datei "accountList.js-meta.xml" mit diesem Code, damit die Komponente auf Anwendungsseiten verfügbar ist:
<?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>
- Speichern Sie alle drei Komponentendateien.
- Stellen Sie den Ordner force-app/main/default in Ihrem Trailhead Playground bereit.
- Navigieren Sie in Ihrem Trailhead Playground zum Lightning App Builder (Anwendungsgenerator) und öffnen Sie die Seite "Working with Data".
- Ziehen Sie die Komponente accountList in den Hauptbereich der Seite.
- Speichern Sie die Seite.
- Kehren Sie zur Seite "Working with Data" zurück, um sich Ihre neue Komponente anzusehen.
Sie kennen jetzt ein paar Möglichkeiten für die Interaktion mit Salesforce-Daten in Ihren Lightning-Webkomponenten. Als Nächstes befassen wir uns damit, wie Sie etwaige Serverfehler behandeln.
Ressourcen