Friday, December 28, 2018

Passing a record Id from a Lightning Component to an APEX Controller

One of the most common things you will come across when working with Lightning Components is the need to pass a record Id to an APEX controller. When we talk about Lightning Components we are referring to an AuraBundleDefinition. Within that Aura bundle there are a number of different items, but for this example, we will only be using the component and the controller. If you want to learn more about the AuraBundleDefinition you can click here. Enough small talk, let's jump right in and take a look at the code.

LightningRecordIdExample.cmp

The first line of the component is where we specify the controller class and implement our interfaces.

<aura:component controller="LightningRecordIdExampleController" implements="flexipage:availableForAllPageTypes,force:hasRecordId"></aura:component>

And as you've probably figured out from the snippet above, the interface used to get the record Id is ...force:hasRecordId". 


The force:hasRecordId interface does a couple of thing to the component that implements it.

  • It adds an attribute named recordId to your component. This attribute is of type String, and its value is an 18-character Salesforce record ID, for example: 001xx000003DGSWAA4. If you added it yourself, the attribute definition would look like the following markup:
<aura:attribute name="recordId" type="String"></aura:attribute>

Note If your component implements force:hasRecordId, you don’t need to add a recordId attribute to the component yourself. If you do add it, don’t change the access level or type of the attribute or the component will cause a runtime error.
  • When your component is invoked in a record context in Lightning Experience or the Salesforce app, the recordId is set to the ID of the record being viewed.

Now that we have our record Id, let's take a look at the Lightning controller class.

LightningRecordIdExample.js

In our controller class, we have a single function call doInit the gets called upon page initialization.

doInit : function(component, event, helper){

This function creates a one-time instance of the getAccount function in the server-side controller.

var action = component.get("c.getAccount");

Next, we set the accountId parameter by getting the recordId attribute value from the component.

action.setParams({
     "accountId": component.get("v.recordId")
});


Now that we have defined the action and added the record Id as a parameter, all that's left to do is to queue the action and handle the callback response.

action.setCallback(this, function(response) {
   var state = response.getState();
   

   if (component.isValid() && state === "SUCCESS") {
      component.set("v.account", response.getReturnValue());
      ...


That's pretty much it! You can check out the server-side controller class below.

Monday, October 8, 2018

Winter '19 Platform Events and the new Lightning Emp API Component

With the Winter '19 release there are a number of lightning updates to help make working with lightning components a little bit easier. For this post, I thought that I'd focus on the new Lightning Emp Api component.

lightning:empApi

Embed the lightning:empApi component in your custom Lightning component to subscribe to a streaming event channel and receive event notifications. You can subscribe to any type of event channel on the Lightning Platform, including channels for platform events, PushTopic and generic events, and Change Data Capture (Developer Preview) events. The lightning:empApicomponent uses a shared CometD-based Streaming API connection, enabling you to run multiple streaming apps in the browser.

One of the nicest things about this new component, is that it greatly reduces the amount of code that I need to copy and paste each time I want to consume a Platform Event. In the past, we had to use the cometd library which required a fair bit of work to setup and initialize. This included downloading the library, creating a static resource, initializing the resource, configuring the endpoint, etc... I'm getting tired just thinking about it. With the new lightning:empApi component, it's just a matter of adding the lightning:empApi component to your custom lightning component, creating a error handler to catch any issues, and subscribing to the event. Pretty easy huh? Now that that's all out of the way, let's take a look at some code.

Let's start off by creating a new Platform Event called "Demo_EmpApi_Event__e"...
...and add a new custom field called "Message__c".

Next, we need to add the reference to Emp API to our lightning component:
  <lightning:empapi aura:id="empApi"></lightning:empapi>
The bulk of the logic is handled by the init method in the controller class. The first thing that we need to do is to get a reference the Emp API component:

  var empApi = cmp.find("empApi");
Once we have a reference to the Emp API component we can subscribe to the event:
  var replayId=-1; //use -1 for new events
  empApi.subscribe(channel, replayId, callback).then(function(value) {
      console.log("Subscribed to channel " + channel);
      sub = value;
      cmp.set("v.sub", sub);
  });
When we receive a message we need to handle is somehow. In this case I've created a callback function to popup an alert.
  var callback = function (message) {
      alert('Event Received!');        
  }.bind(this);

The final piece of this is to publish the event. In order to do so, I've created an Apex class that instantiates the Demo_EmpApi_Event__e and then uses the EventBus Class to publish it.
  Demo_EmpApi_Event__e event = new Demo_EmpApi_Event__e(Message__c=message);      
  Database.SaveResult result = EventBus.publish(event);

That's pretty much it! Now when we publish an event we get an alert.

I've posted the complete code examples below. Happy coding!

EmpApi_example.cmp
EmpApi_exampleController.js 
EmpApi_exampleController.cls

Saturday, April 7, 2018

Lightning Knowledge Promoted Terms in Spring'18

I've been working on migrating our current Service Console from Classic to Lightning and although Salesforce has been adding new features to Lightning, I continue to run into parity issues. As of Spring '18 there are still key features that are not yet available in Lightning Knowledge. One of these key features is the use of Promoted Search Terms. One of the ways that we help our agents find knowledge articles is to use Promoted Search Terms to promote articles in the search results. This has worked well in Classic, but thus far this feature is not available in Lightning. To bridge the gap, I've created a Lightning App that let's the knowledge admins add Promoted Terms to existing articles. The APEX code to do just that is surprisingly simple.


Let's take a closer look at the code. After selecting the article by Id, we create a new instance of a SearchPromotionRule where we provide the search term (Query='Trailblazer') and the article Id to promote (PromotedEntityId=articles[0].Id);). The last line simply inserts the record. That's pretty much all there is to it.

A couple of things to note:
  • The user must have the "Manage Promoted Search Terms" permission.
  • The search term can be a maximum of 100 characters.
  • A search term can be associated with multiple articles.


Create a Lightning Component that Utilizes the Native Salesforce Global Search

I was recently working on a project where I needed to create Lightning Component that utilized the native global search to return items from...