Erfassen Sie Ihre Fortschritte
Trailhead-Startseite
Trailhead-Startseite

Kennenlernen von Lightning-Aktionen

Lernziele

Nachdem Sie diese Lektion abgeschlossen haben, sind Sie in der Lage, die folgenden Aufgaben auszuführen:
  • Erstellen einer Aura-Komponente und -Aktion zum Auffüllen von Feldern basierend auf der Benutzereingabe und Anzeigen von Feedbackmeldungen für Benutzer
  • Erstellen einer Aura-Komponente und -Aktion für die Integration in ein System eines anderen Anbieters
  • Beginnen der Migration Ihrer JavaScript-Schaltflächenfunktionalität zu von Lightning gestützten Alternativen

Lightning-Aktionen: Intelligent, schnell und mobil

Wir haben verschiedene Lösungen vorgestellt, die sowohl in Lightning Experience als auch Salesforce Classic funktionieren und sich sehr gut als Ersatz für JavaScript-Schaltflächen eignen. Doch uns ist klar, dass diese deklarativen und programmgesteuerten Lösungen sich nicht für jeden Anwendungsfall eignen. Die gute Nachricht ist, dass es etwas gibt, was sich für viele weitere eignet. Die Rede ist von Lightning-Aktionen, bei denen es sich um Schnellaktionen handelt, die Lightning-Komponenten aufrufen.
Hinweis

Hinweis

Ab dem Release Spring'19 (API-Version 45.0) können Sie Lightning-Komponenten mithilfe von zwei Programmiermodellen erstellen: dem Modell "Lightning-Webkomponenten" und dem ursprünglichen Modell "Aura-Komponenten". Lightning-Webkomponenten und Aura-Komponenten können auf einer Seite nebeneinander vorhanden sein und interagieren. In diesem Abschnitt werden Aura-Komponenten behandelt.

Lightning-Aktionen bauen auf dem vorhandene Lightning Component-Framework auf. Sie können Ihre vorhandenen Aura-Komponenten mühelos in Aktionen umwandeln und sie in der mobilen Salesforce-Anwendung und Lightning Experience nutzen.

Sie verwandeln eine Aura-Komponente in eine aufrufbare Aktion, indem Sie der Komponente eine von zwei Schnittstellen hinzufügen: force:lightningQuickAction or force:lightningQuickActionWithoutHeader. Die erste Schnittstelle fügt dem Lightning-Aktions-Overlay die Standardkopfzeile mit den Schaltflächen "Speichern" und "Abbrechen" hinzu, die andere dagegen nicht.

Eine weitere nützliche Schnittstelle für eine Lightning-Aktion ist force:hasRecordId, die der Komponente den Datensatzkontext bereitstellt, wenn sie auf einer Datensatzseite aufgerufen wird. Wenn Sie Ihre Lightning-Aktion als globale Schnellaktion einrichten, benötigen Sie den Datensatzkontext nicht. Wenn Sie jedoch auf die Daten oder Metadaten eines Datensatzes zugreifen möchten, müssen Sie force:hasRecordId implementieren.

Hinweis

Hinweis

Falls Sie bislang noch keine Aura-Komponenten erstellt haben, führen Sie im Lightning Development Center das Projekt Lightning Component Quick Start aus und arbeiten das Modul Aura-Komponenten – Grundlagen durch.

Lassen Sie uns Lightning-Aktionen nun etwas genauer ansehen. Als Nächstes beschäftigen wir uns mit JavaScript-Schaltflächenfunktionalität, die stattdessen von Lightning-Aktionen ausgeführt werden kann.
  • Auffüllen von Feldern basierend auf der Benutzereingabe und Anzeigen von Feedbackmeldungen während der Dateneingabe
  • Integrieren von APIs anderer Anbieter

Auffüllen von Feldern basierend auf der Benutzereingabe und Anzeigen von Feedbackmeldungen für Benutzer

Angenommen, Sie nutzen JavaScript-Schaltflächen zum Überprüfen oder Bearbeiten von Daten oder um Ihren Benutzern Feedback oder Anweisungen zu geben, wenn sie mit Datensätzen arbeiten. Es folgt ein Beispiel, wie mühelos Sie Daten in einer Lightning-Komponente überprüfen oder bearbeiten können, ehe Ihre Benutzer einen Datensatz erstellen oder aktualisieren.

In unserer Beispielorganisation haben wir das benutzerdefinierte Objekt "Case Study" erstellt, mit dessen Hilfe wir verschiedene Forschungsprojekte nachverfolgen. Wenn wir neue Testbenutzer hinzufügen, erfassen wir ihre Namen und E-Mail-Adressen. Da die E-Mail-Adresse unsere primäre Kontaktmethode ist, möchten wir sicherstellen, dass sie ordnungsgemäß eingegeben wird. Wir möchten außerdem für Testbenutzer einen eindeutigen Spitznamen erstellen, damit sie anonym bleiben können.

Wir erstellen eine Lightning-Aktion, die die Felder für den Namen und die E-Mail-Adresse anzeigt, die E-Mail-Adresse überprüft und aus dem Vornamen und einer Zufallszahl automatisch den Spitznamen erstellt.

Hier ist der Code für die Komponente, die von dieser Lightning-Aktion aufgerufen wird.
  • CreateUser.cmp: Die Lightning-Komponente, die angezeigt wird, wenn Sie die Aktion öffnen. Sie enthält die Benutzeroberflächenimplementierung, wozu die Textfelder, Schaltflächen, der Aktionstitel usw. gehören.
  • CreateUserController.js: Der Controller, der die Komponente und alle auf der Benutzeroberfläche erfolgenden Ereignisse überwacht, wie z. B. den ersten Ladevorgang, Texteingaben und Klicks auf Schaltflächen. Seine Aufgabe ist das Delegieren dieser Ereignisse an die Hilfsklasse CreateUserHelper.js.
  • CreateUserHelper.js: Der Code zum Verarbeiten der gesamten Geschäftslogik, z. B. Überprüfen der Felder für das Kennwort und die E-Mail-Adresse.

CreateUser.cmp

<aura:component implements="force:lightningQuickActionWithoutHeader,force:hasRecordId">
    <aura:attribute name="user" type="Test_User__c" default="{}"/>
    <aura:attribute name="hasErrors" type="Boolean" description="Indicate whether there were failures or not" />
    <aura:attribute name="caseStudy" type="String" />
    <aura:attribute name="recordId" type="String"/>
    <aura:attribute name="errorFromCreate" type="String"/>

    <!-- <aura:handler name="init" value="{!this}" action="{!c.init}" />  -->

    <force:recordData aura:id="frd" mode="EDIT" layoutType="FULL"/>
    
    <div class="slds-page-header" role="banner">
    	<p class="slds-text-heading--label">Case Study</p>
        <h1 class="slds-page-header__title slds-m-right--small slds-truncate slds-align-left" title="Case Study Title">{!v.caseStudy}</h1>
    </div>
    <br/>
    
    <aura:if isTrue="{!v.hasErrors}">
        <div class="userCreateError">
            <ui:message title="Error" severity="error" closable="true">
                Please review the error messages.
            </ui:message>
        </div>
    </aura:if>

    <div class="slds-form--stacked">
                
        <div class="slds-form-element">
            <label class="slds-form-element__label" for="firstName">Enter first name: </label>
            <div class="slds-form-element__control">
              <ui:inputText class="slds-input" aura:id="firstName" value="{!v.user.First}" required="true" keydown="{!c.updateNickname}" updateOn="keydown"/>
            </div>
        </div>
        
        <div class="slds-form-element">
            <label class="slds-form-element__label" for="lastName">Enter last name: </label>
            <div class="slds-form-element__control">
              <ui:inputText class="slds-input" aura:id="lastName" value="{!v.user.Last}" required="true" />
            </div>
        </div>
        
        <div class="slds-form-element">
            <label class="slds-form-element__label" for="nickname">Enter nickname: </label>
            <div class="slds-form-element__control">
              <ui:inputText class="slds-input" aura:id="nickname" value="{!v.user.Nickname}" required="false"/>
            </div>
        </div>
        
        <div class="slds-form-element">
        	<label class="slds-form-element__label" for="userEmail">Enter user's email:</label>
            <div class="slds-form-element__control">
        		<ui:inputEmail class="slds-input" aura:id="userEmail" value="{!v.user.Email__c}" required="true"/>
            </div>
        </div>
        
        <div class="slds-form-element">
        	<label class="slds-form-element__label" for="userPassword">Enter user's password:</label>
            <div class="slds-form-element__control">
        		<ui:inputSecret class="slds-input" aura:id="userPassword" value="{!v.user.Password__c}" required="true"/>
            </div>
        </div>
        
        <div class="slds-form-element">
        	<ui:button class="slds-button slds-button--neutral" press="{!c.cancel}" label="Cancel" />
        	<ui:button class="slds-button slds-button--brand" press="{!c.saveUserForm}" label="Save User" />
        </div>
    </div>

</aura:component>

CreateUserController.js

({    
    /**
     * Auto generate the username from firstName on tab
     */
    updateNickname: function(component, event, helper) {
        // Update the nickname field when 'tab' is pressed
        if (event.getParams().keyCode == 9) {
        	var nameInput = component.find("firstName");
        	var nameValue = nameInput.get("v.value");
        	var nickName = component.find("nickname");
            var today = new Date();
        	nickName.set("v.value", nameValue + today.valueOf(today));   
        }
    },
 
    /**
     * Capture the Inputs and invoke the helper.save with the input params 
     */
	saveUserForm : function(component, event, helper) {
        var name = component.get("v.user.First");
        var last = component.get("v.user.Last");
        var password = component.get("v.user.Password__c");
        var email = component.get("v.user.Email__c");
        var nickname = component.get("v.user.Nickname");
        
        var passwordCmp = component.find("userPassword");
        var emailCmp = component.find("userEmail");
        
        helper.validatePassword(component, event, helper);
        helper.validateEmail(component, event, helper);

        if (passwordCmp.get("v.errors") == null && emailCmp.get("v.errors") == null) {
            component.set("v.hasErrors", false);
        	helper.save(component, name + " " + last, password, email, nickname);         
        } else {
            component.set("v.hasErrors", true);
        }
    },
    
    cancel : function(component, event, helper) {
        $A.get("e.force:closeQuickAction").fire();
    }
})

CreateUserHelper.js

({  
    save: function(component, name, password, email, nickname) {
        // Create a user record, save it, and close the panel
        var userRecord = {apiName: 'Test_User__c', fields: {}};
        userRecord.fields.Name = {value: name};
        userRecord.fields.Password__c = {value: password};
        userRecord.fields.Email__c = {value: email};
        userRecord.fields.Nickname__c = {value: nickname};
        userRecord.fields.Case_Study__c = {value: component.get("v.recordId")};
        // get the force:recordData and set the targetRecord
        component.find("frd").set('v.targetRecord', userRecord); 
        // invoke saveRecord of force:recordData
        component.find("frd").saveRecord($A.getCallback(function(response) {
            if (component.isValid() && response.state == "SUCCESS") {
                $A.get("e.force:closeQuickAction").fire();
                var toastEvent = $A.get("e.force:showToast");
                toastEvent.setParams({
                	"title": "Success!",
                    "message": "The test user has been created."
                });
                toastEvent.fire();		
                $A.get('e.force:refreshView').fire();
            } else if (response.state == "ERROR") {
                console.log('There was a problem and the state is: '+ response.state);
            }
        }));
    },
    
    validatePassword : function(component, event, helper) {
        var inputCmp = component.find("userPassword");
        var value = inputCmp.get("v.value");
        
        if (value == undefined) {
           inputCmp.set("v.errors", [{message: "You must enter a password."}]);
        } else if (value.length < 7 || value.length > 15) {
            inputCmp.set("v.errors", [{message: "The password is the wrong length (must be <= 15): " + value.length}]);
        } else if (value.search(/[0-9]+/) == -1) {
            inputCmp.set("v.errors", [{message: "The password must contain at least one number."}]);
        } else if (value.search(/[a-zA-Z]+/) == -1) {
            inputCmp.set("v.errors", [{message: "The password must contain at least one letter."}]);
        } else {
            inputCmp.set("v.errors", null);
        }
	},
    
    validateEmail : function(component, event, helper) {
        var inputCmp = component.find("userEmail");
        var value = inputCmp.get("v.value");
        
        if (value == undefined) {
           inputCmp.set("v.errors", [{message: "You must enter an email."}]);
           return;
        }
        
        var apos = value.indexOf("@");
        var dotpos = value.lastIndexOf(".");

        if (apos<1||dotpos-apos<2){
            inputCmp.set("v.errors", [{message: "Email is not in the correct format: " + value}]);
        } else if (value.substring(apos+1, dotpos) != "gmail") {
            inputCmp.set("v.errors", [{message: "Email must be a gmail account: " + value.substring(apos+1, dotpos)}]);
        } else {
            inputCmp.set("v.errors", null);
        }
	}
})

Nachdem wird die Lightning-Komponente erstellt haben, weisen wir sie einer Aktion zu. In den Objektverwaltungseinstellungen für "Case Study" wechseln wir zu "Schaltflächen, Links und Aktionen", klicken auf Neue Aktion und konfigurieren dann die Aktion mit diesen Parametern.

Feld Wert
Objektname Case Study
Aktionstyp Lightning-Komponente
Lightning-Komponente c:CreateUser
Höhe 500px
Bezeichnung Testbenutzer erstellen
Name CreateUser

Anschließend fügen wir unsere neue Lightning-Aktion dem Layout der Seite "Case Study" hinzu. Wenn Benutzer Sie auf der Datensatzseite "Case Study" aufrufen, sehen Sie die von uns erstellte Lightning-Aktion.

Testbenutzer erstellen, Lightning-Aktions-Overlay

Der große Vorteil dieser Lightning-Aktion ist, dass sie auch in der mobilen Salesforce-Anwendung funktioniert.

Aktion 'Fallstudie' in der Salesforce-Anwendung

Integrieren von APIs anderer Anbieter

Vielleicht nutzen Sie JavaScript-Schaltflächen für die Integration in Systeme anderer Anbieter. Können Sie Lightning-Aktionen dazu verwenden? Natürlich können Sie das. Der Hauptunterschied ist, dass Sie für die Integration mithilfe von Lightning-Aktionen einen serverseitigen Controller verwenden müssen. Im Gegenzug erhalten Sie einen sicheren Umgang mit Anmeldeinformationen und die Möglichkeit, Apex für asynchrone und API-Batchaufrufe zu nutzen.

Lassen Sie uns nun anschauen, wie die Integration in Twilio zum Senden von SMS-Nachrichten erfolgt. Bei diesem Beispiel sind wir im Luxusreisen-Segment tätig und haben mit Stars und Promis zu tun. Wir möchten, dass unsere Kundenservicemitarbeiter mit ihren Klienten kommunizieren können, möchten jedoch die persönlichen Kontaktinformationen der Klienten niemandem preisgeben. Wir erstellen eine Lightning-Aktion für das Objekt "Kontakt", die es Mitarbeitern ermöglicht, Nachrichten zu senden, ohne die Telefonnummer des Kontakts zu sehen.

Wie in unserem Beispiel zu "Case Study" erstellen wir die Aura-Komponente und Hilfsklassen und anschließend eine Schnellaktion zum Aufrufen der Komponente.

SMS, Lightning-Aktions-Overlay

Diese Lightning-Aktion besteht aus der Aura-Komponente, einem JavaScript-Controller und einem Apex-Controller, der auf Bibliotheksklassen verweist, die die Twilio-Integration übernehmen.

SendTwilioSMS.cmp

<aura:component controller="TwilioSendSMSController" implements="flexipage:availableForAllPageTypes,force:hasRecordId,force:lightningQuickAction" >
   <aura:attribute name="textMessage" type="String" />
   <aura:attribute name="destinationNumber" type="String" />
   <aura:attribute name="messageError" type="Boolean" />
   <aura:attribute name="recordId" type="String" />

      <aura:handler name="init" value="{!this}" action="{!c.init}" />

   <aura:if isTrue="{!v.messageError}">
      <!-- Load error -->
      <div class="userCreateError">
         <ui:message title="Error" severity="error" closable="true">
            Unable to send message. Please review your data and try again.
         </ui:message>
      </div>
   </aura:if>

   <div class="slds-form--stacked">
      <label class="slds-form-element__label" for="instructMsg">Please enter the message (max 160 char) below: </label>
      <br/>
      <div class="slds-form-element__control">
         <ui:inputText class="slds-input" aura:id="message" label="Text Message" value="{!v.textMessage}" required="true" maxlength="160" size="165" />
      </div>
      <div class="centered">
         <ui:button class="slds-button slds-button--brand" press="{!c.sendMessage}" label="Send Message"/>
      </div>
   </div>
</aura:component>

SendTwilioSmsController.js

({
   init : function(component, event, helper) {
      var action = component.get("c.getPhoneNumber");
      action.setParams({"contactId": component.get("v.recordId")});
      action.setCallback(this, function(response) {
         var state = response.getState();
         if(component.isValid() && state == "SUCCESS"){
            component.set("v.destinationNumber", response.getReturnValue());
         } else {
            component.set("v.messageError", true);
         }
      });
      $A.enqueueAction(action);
   },

      sendMessage : function(component, event, helper) {
      var smsMessage = component.get("v.textMessage");
      var number = component.get("v.destinationNumber");
      var recordId = component.get("v.recordId")

      var action = component.get("c.sendMessages");
      action.setParams({"mobNumber": number, "message": smsMessage, "contactId": component.get("v.recordId")});
      action.setCallback(this, function(response) {
         var state = response.getState();
         if(component.isValid() && state == "SUCCESS"){
            $A.get("e.force:closeQuickAction").fire();
            var toastEvent = $A.get("e.force:showToast");
            toastEvent.setParams({
               "title": "Success!",
               "message": "SMS has been sent woo hoo!"
            });
            toastEvent.fire();
         } else {
            component.set("v.messageError", true);
         }
      });
      $A.enqueueAction(action);
   }
})

SendTwilioSmsController.apxc

/*
* Apex controller that currently contains only one method to send sms message
*/
global class TwilioSendSMSController {

   /*
   * This method uses the Twilio for Salesforce library class and method to
   * send the message using the Twilio api.
   */
   @AuraEnabled
      webService static String sendMessages(String mobNumber, String message, Id contactId) {
         System.debug('the mobNumber is: '+ mobNumber + ' and the message is: '+ message + ' and contactId is: ' + contactId);

         if (mobNumber == null) {
            mobNumber = getPhoneNumber(contactId);
         }

         try {
            TwilioRestClient client = TwilioAPI.getDefaultClient();

            Map<String,String> params = new Map<String,String> {
               'To' => mobNumber,
               'From' => '15555551234',
               'Body' => message
               };
            TwilioSMS sms = client.getAccount().getSMSMessages().create(params);
            return sms.getStatus();
         } catch(exception ex) {
            System.debug('oh no, it failed: '+ex);
            return 'failed';
         }
      }

      @AuraEnabled
      public static String getPhoneNumber(Id contactId) {
         Contact currentRecord = [SELECT Phone FROM Contact WHERE Id = :contactId];
         return currentRecord.Phone.replace(' ', '').replace('-', '').replace(')', '').replace('(', '');
   }
}

Nachdem wird die Lightning-Komponente erstellt haben, erstellen wir eine Lightning-Aktion. Dieses Mal fügen wir sie dem Seitenlayout "Kontakt" hinzu, damit Mitarbeiter darauf zugreifen können.

Der große Vorteil ist wiederum, dass die Aktion auch in der mobilen Salesforce-Anwendung verfügbar ist. Wenn ein Limousinenservice versucht, den Kunden am Flughafen zu kontaktieren, kann der Fahrer den Kunden mühelos über ein Mobilgerät erreichen.

Lightning-Aktion 'SMS' in der Salesforce-Anwendung

Lightning-Aktionen sind die Zukunft programmgesteuerter Aktionen in Lightning Experience. Wir hoffen, dass Sie beginnen, sich mit diesem Angebot an Lösungen als bessere Alternative zu JavaScript-Schaltflächen zu beschäftigen.

Wenn Sie von Partneranwendungen abhängig sein sollten, die JavaScript-Schaltflächen nutzen, wird es Sie freuen zu hören, dass viele unserer Partner bereits mit der Migration und dem Upgrade ihrer Anwendungen zu Lightning begonnen haben. In AppExchange finden Sie weitere Anwendungen, die für Lightning Experience aktualisiert wurden.

Jenseits der Grundlagen

Wenn Sie Twilio selbst ausprobieren möchten, finden Sie ein nicht verwaltetes Paket der Bibliotheksklasse "Twilio for Salesforce", die im Beispiel der Integration in eine Drittanbieterlösung verwendet wird, in der Salesforce-Bibliothek auf GitHub: https://github.com/twilio/twilio-salesforce

Erstellen Sie vor dem Verwenden von Twilio for Salesforce und der Twilio-API einen Twilio-Account, richten Sie eine Telefonnummer ein und verbinden Sie Ihren Account mit Salesforce. Unter TwilioApi.cls in der GitHub-Bibliothek finden Sie weitere detaillierte Anweisungen.