Lightning Component Events - Change Types with Care
Introduction
After the Spring 16 release of Salesforce went live, one of the components from my BrightMedia mobile booking application started throwing errors when sending a booking and its line items back to the Salesforce server. After some investigation, it turned out that the JavaScript version of the Order sObject had gained a ‘serId’ attribute somewhere along the line, which broke the deserialisation on the server.
One aspect of the application is that the order information is passed around between a number of components using Lighting Events - mainly application events, but there is the odd component event in there, so I set out to see if I could reproduce the error with a noddy application that fired and consumed a few events. I wasn’t able to reproduce the error, but along the way I did manage cause an interesting and unexpected error at deployment time.
Lightning Event Types
There are two types of events in the Lightning Components framework:
Application Events
Application Events follow the Publish-Subscribe pattern. Publisher Components fire events without any knowledge of which other components may consume them, while Subscribe Components receive and process events without any knowledge of which, or how many, components have fired them.
An application event specifies its type as ‘APPLICATION’ in the event bundle:
<aura:event type="APPLICATION"
description=“Event fired when something happens" />
A publisher component declares that it will fire the application event via the register event component:
<aura:registerEvent name="MyEvent" type="c:MyAppEvt"/>
A subscriber component declares that it wishes to handle events of this type via the handle event component, which also specifies the controller method to execute when an event of this type is to be removed:
<aura:handler event="c:MyAppEvt" action="{!c.handleMyAppEvt}" />
Component Events
Component Events are a bit more like JavaScript events fired in response to a user action - they can be handled by the component that fires the event (although the last time I tried this I couldn’t get it working) or it can bubble up through the component hierarchy, so being handled by the parent component that contains the publisher component, or its parent, and so on.
A component event specifies its type as ‘COMPONENT’ in the event bundle:
<aura:event type="COMPONENT" description="Another event"/>
A publisher component declares that it will fire the component event via the register event component, specifying
<aura:registerEvent name="MyCompEvent" type="c:MyAppEvt"/>
A consumer component declares that it wishes to handle events of this type via the handle event component - this specifies the name attribute, which must match the name attribute of the register event declaration in the publisher component:
<aura:handler name=“MyCompEvent” event="c:MyCompEvt" action="{!c.handleMyCompEvt}" />
The Problem
When I wrote my noddy application, I defined my event has being of type APPLICATION, but not matter how many times I sent the custom object between components, I couldn’t get the bonus attribute. I then decided to change the type of the event to COMPONENT and update my components to handle the event through the bubbling mechanism. Unfortunately I didn’t carry out the latter task, as one of my many other duties took precedence, and I quickly forgot about it. Obviously this was in a developer edition and for a disposable application, in a real-world customer environment I’d create a new event rather than changing the behaviour of an existing one.
The next time that I tried to deploy an (unrelated) aura component via the metadata API, around a week later, I got the following error:
which rather confused me, as I didn’t have any event handlers in the component. After retrieving all of my lightning components via the Force CLI, I was able to search for component events, a synapse fired, and I remembered half changing my test component.
So it appears that when you deploy an aura component via the metadata API, a validation type check is carried out on all existing components to make sure that everything is coherent. This may happen with other deployment methods, I haven’t tested with any others. It doesn’t happen in the Developer Console, as that was the tool that I used to update the component. This makes sense, as otherwise it would be impossible to change anything that briefly invalidated another component.
By the way, if you are wondering what I did about the bonus attributes, I came up with a couple of workarounds:
- Turn it into a JSON string an remove the attribute during the conversion
- Delete the attribute using the JavaScript delete keyword