Descubrir las acciones de Lightning
Objetivos de aprendizaje
- Crear un componente y una acción Aura para completar campos en función de la entrada del usuario y generar mensajes de comentarios para los usuarios.
- Crear un componente y una acción Aura que se integren con un sistema externo.
- Iniciar la migración de la funcionalidad de los botones personalizados de JavaScript a alternativas compatibles con Lightning.
Acciones de Lightning: inteligentes, rápidas y móviles

Nota
Desde la versión Spring ‘19 (versión 45.0 de la API), puede construir componentes Lightning empleando dos modelos de programación: el modelo Componentes web Lightning y el modelo Componentes Aura original. Los componentes web Lightning y los componentes Aura pueden coexistir y funcionar conjuntamente en una página. Este contenido trata los componentes Aura.
Las acciones Lightning están construidas sobre el marco de trabajo de componentes Lightning existente. Puede convertir fácilmente los componentes Aura existentes en acciones y usarlas en la aplicación móvil Salesforce y Lightning Experience.
Para poder invocar un componente Aura como una acción, agregue una de estas dos interfaces al componente: force:lightningQuickAction o force:lightningQuickActionWithoutHeader. La primera interfaz agrega el encabezado estándar con los botones Guardar y Cancelar a la superposición de la acción de Lightning, pero la otra interfaz no sirve para esto.
Otra interfaz útil para una acción de Lightning es force:hasRecordId, la cual proporciona el contexto de registro para el componente cuando se invoca desde una página de registro. Si configura su acción de Lightning como una acción rápida global, no necesita el contexto de registro. No obstante, si desea acceder a los datos o metadatos de un registro, debe implementar force:hasRecordId.

Nota
Si no ha creado componentes Aura antes, visite el centro de desarrollo de Lightning, complete el proyecto de inicio rápido de componentes Aura y complete el módulo Fundamentos de Componentes Aura.
- Llenado de campos en función de la entrada del usuario y generación de mensajes de comentarios durante la entrada de datos
- Integración con API externas
Completar campos en función de la entrada del usuario y generar mensajes de comentarios para los usuarios
Hemos creado un objeto personalizado en nuestra organización de ejemplo, llamada Caso práctico, el cual usamos para hacer un seguimiento de distintos proyectos de investigación. Al agregar nuevos usuarios de prueba, capturamos sus nombres y direcciones de email. Dado que la dirección de email es nuestro método de contacto principal, queremos asegurarnos de que se ingresa correctamente. Además, queremos crear un apodo único para los usuarios de prueba de modo que puedan seguir siendo anónimos.
Vamos a crear una acción de Lightning que muestre los campos de nombre y dirección de email, valide la dirección de email y use el nombre y un número aleatorio para crear el apodo automáticamente.
- CreateUser.cmp: El componente Lightning que ve al abrir la acción. Contiene la implementación de la interfaz de usuario, lo que incluye campos de texto, botones, el título de la acción, etc.
- CreateUserController.js: El controlador que escucha el componente y cualquier evento de interfaz de usuario, como la carga inicial, la entrada de texto y los clics en botones. Su función es delegar estos eventos en la clase auxiliar CreateUserHelper.js.
- CreateUserHelper.js: El código que trata toda la lógica de negocio, como la validación de los campos de email y contraseña.
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); } } })
Después de crear el componente Lightning, lo asignamos a una acción. En la configuración de gestión de objetos para el caso práctico, vamos a Botones, vínculos y acciones, hacemos clic en Nueva acción y, a continuación, configuramos la acción con estos parámetros.
Campo | Valor |
---|---|
Nombre de objeto | Caso práctico |
Tipo de acción | Componente Lightning |
Componente Lightning | c:CreateUser |
Altura | 500px |
Etiqueta | Crear usuario de prueba |
Nombre | CreateUser |
A continuación, agregamos la nueva acción de Lightning al formato de página del caso práctico. Cuando los usuarios la invocan desde una página de registro del caso práctico, ven la acción de Lightning que hemos creado.
Lo mejor de esta acción de Lightning es que también funciona en la aplicación móvil Salesforce.
Integrar API externas
Vamos a describir cómo realizar una integración con Twilio para el envío de mensajes SMS. En este ejemplo, nos vamos a centrar en el negocio de los viajes de lujo y nos relacionaremos con celebridades y personas muy importantes. Nuestro objetivo es que los agentes del servicio de atención al cliente puedan comunicarse con sus clientes, pero no queremos revelar en ningún caso la información de contacto personal de los clientes. Creamos una acción de Lightning en el objeto Contacto para que los agentes puedan enviar mensajes sin ver el número de teléfono del contacto.
Como en nuestro ejemplo de caso práctico, creamos el componente Aura y clases auxiliares y, a continuación, creamos una acción rápida para invocar el componente.
Esta acción de Lightning consta de un componente Aura, un controlador de JavaScript y un controlador de Apex, el cual hace referencia a las clases de la biblioteca que procesan la integración con Twilio.
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('(', ''); } }
Después de crear el componente, creamos una acción de Lightning. En esta ocasión, la agregamos al formato de página de contactos para que los agentes puedan acceder a la acción.
Una vez más, la parte interesante es que la acción también está disponible en la aplicación móvil Salesforce. Si un proveedor de servicios de vehículos intenta hacer contacto con el cliente en el aeropuerto, el conductor puede usar un dispositivo móvil para tener acceso al cliente fácilmente.
Las acciones de Lightning son el futuro de las acciones programáticas en Lightning Experience. Esperamos que empiece a considerar este conjunto de soluciones como una alternativa mejor a los botones de JavaScript.
Además, si depende de aplicaciones de socios que usan botones de JavaScript, le alegrará saber que muchos de nuestros socios ya han empezado a migrar y actualizar sus aplicaciones a Lightning. Encontrará más aplicaciones en AppExchange, las cuales están actualizadas para Lightning Experience.
Más allá de los fundamentos
Si desea probar Twilio por su cuenta, dispone de un paquete no gestionado de Twilio para la clase de la biblioteca de Salesforce usada en el ejemplo de integración con terceros en la biblioteca Github de https://github.com/twilio/twilio-salesforce
Antes de usar Twilio para Salesforce y la API de Twilio, cree una cuenta de Twilio, configure un número de teléfono y conecte su cuenta a Salesforce. Consulte TwilioApi.cls en la biblioteca Github para obtener instrucciones más detalladas.