Easy Component Events in Salesforce Lightning

Jon Balza
4 min readNov 12, 2018

--

In Salesforce Lightning, when creating a large app or a set of components such as a community, you want to create small, reusable Lightning components that help you maintain consistency and help with maintenance and scalability. To allow that reusability, you’ll want to use component or application events, which lets you use different event handlers with the same component. A good example of this may be a case submission form with both a save and a reset button.

Photo by Felix Mittermeier on Unsplash

Unfortunately, Salesforce Lightning events for dealing with those buttons across a variety of different forms can be a bit of a beast to deal with. As you scale, the amount of code overhead can be both a bit inelegant and creates a large amount of code to work with. The Salesforce Documentation discusses component event handling using a similar method to what I describe below:

Salesforce’s method, as described in their documentation

First, setup the event itself. A type attribute can be used to determine the kind of action that is fired by the button.

<!-- ButtonEvent.evt -->
<aura:event type="COMPONENT">
<aura:attribute name="type" type="String" />
</aura:event>

Now, setup a CustomButton component with some basic attributes to help display the different button labels and fire the onclick event for the button.

<!-- CustomButton.cmp -->
<aura:component description="CustomButton">
<aura:attribute name="type" type="String" />
<aura:attribute name="label" type="String" />
<aura:registerEvent name="onclick" type="c:ButtonEvent" />
<button onclick="{!c.handleButtonClick}">
{!v.label}
</button>
</aura:component>

The type attribute isn’t being used directly in the component, but it’s used in the controller that fires the ButtonEvent that we just registered. Here’s what that controller looks like:

/* CustomButtonController.js */
({
handleButtonClick: function (component, event) {
var event = component.getEvent("onclick");
event.setParams({
type: component.get("v.type")
});
event.fire();
}
})

OK, that’s not so bad. We have a CustomButton component that fires an event when clicked, and it provides a type parameter that we can use to pass save or reset to. What’s the fuss? The problem comes in with the code that you need to write to handle that event. Let’s create a Form component with two buttons first:

<!-- Form.cmp -->
<aura:component description="Form">
<! — Any attributes here -->
<aura:handler name="onclick" event="c:ButtonEvent" action="{!c.handleClick}" />
<div>
<!-- Form fields go here -->
<CustomButton type="reset" label="Reset Form" />
<CustomButton type="save" label="Save Form" />
</div>
</aura:component>

Note the two CustomButton components we’ve embedded in our form, one to handle the save action, and the other to reset the form. The key part is the event handler we’ve created. Note that it uses the same onclick name as what we created in CustomButton.cmp , and then we tell it to expect an event of type c:ButtonEvent , which is the first event we created. When that event is handled, it fires the handleClick action.

So now there is one event that can be handled, but we’re embedding two buttons! We need going to have to deal with that, and here’s where the type parameter in the handleClick action comes in handy.

/* FormController.js */
({
handleClick: function (component, event) {
var type = event.getParam("type");
switch (type) {
case "save":
// Do the save action here
break;
case "reset":
// Do the reset action here
break;
}
}
})

OK, one handleClick action that takes the type we’ve created, and lets you do something to differentiate between the two buttons. That’s not so bad, but you can see the switch statement is going to get to be unwieldy if we add other event types, like cancel or save_as_draft. Additionally, in the Form component, we have a lot of boilerplate code needed to handle it, such the <aura:handler /> for the onclick event. To me, it just feels weird to write a single handleClick for multiple components.

A better way to write a Salesforce Lightning Component Event Handler

Having used ReactJS for about 2 years, and loving how their events are handled, I was determined to find a better way. In React, I would pass an event down as a prop on the component. Here, let’s try passing the event as an attribute directly to the component. Let’s try it here:

<!-- Form.cmp -->
<aura:component description="Form">
<!-- Any attributes here -->
<div>
<!-- Form fields go here -->
<CustomButton type="reset" label="Reset Form" onclick="{!c.handleReset}" />
<CustomButton type=”save” label=”Save Form” onclick="{!c.handleSave}" />
</div>
</aura:component>

OK, that feels a bit easier to understand, but it’s probably a bit different than what you may be used to in Lightning. I’ve removed the <aura:handler /> , and replaced it with onclick attributes directly on the CustomButton component. The amazing thing is, this works, but Salesforce docs don’t really talk about it. To me, that’s a big miss, because it is supported and has the dual advantage of less boilerplate code and easier to read handlers.

So, normally you would have to use an <aura:handler /> in your component, but in reality, you don’t actually have to. All you need is the <aura:registerEvent /> that we already have in our CustomButton component. Now, it looks a lot like React, and the two separate actions seem pretty easy to deal with. Speaking of which, let’s check out our revised controller:

/* FormController.js */
({
handleSave: function (component, event) {
// Do the save action here
},
handleReset: function (component, event) {
// Do the reset action here
}
})

That’s a lot easier, and a lot more scalable. Inspired by React, implemented in Salesforce Lightning.

--

--

Jon Balza

Web Designer & UI Developer at 7Summits specializing in Salesforce Community Cloud-led solutions. • 5+ Salesforce certifications • jonbalza.com