A Flash of Lightning

During Dreamforce '14, Lightning made a big splash. For those of you who don't know, Lightning is the recently renamed Aura component UI framework with a stronger focus on client-side controllers. Why the rename, I don't know, but I guess Lightning fits better with the whole cloud motif. (Coming next year: Salesforce Thunder, Salesforce Squall, Salesforce Cumulonimbus).

And so, on a stage surrounded by 7 or so inward facing screens (shouldn't those be facing the audience? I can't see anything from back here!) a woman whose name I forget demonstrated the ease in which she could create mobile apps with the Lightning App Builder. She dragged and dropped a few components, resized them with a few clicks and voila! You have just built your first app!

While the crowd clapped one of my non-developer managers asked me how useful this actually was. I gave him a BS answer ("It'll streamline mobile development!"), but to be honest I had no idea. Because as nice as this was, you still need to build the actual components, which the presenter conveniently glossed over. I know walking through code doesn't make for engaging presentations, but you can't just throw in some buzz words like jQuery and Javascript and call it a day!

How to Build Lightning Apps

Off to the Developer Zone I go.

One of the challenges in the Developer Zone was building a simple Lightning component. I had never been to Dreamforce before so sitting down to do some actual coding that I could do at home seemed weird, but it turned out to be a nice way to meet some other developers, plus I really wanted that Tile they were giving away for completing the challenges (which, by the way, doesn't work on Android yet so my Tile does little more than an actual tile).

A Taste of Building a Lightning Component

The app was a simple component with two inputs: one for Celsius and one for Fahrenheit. Celsius should default to 0 and Fahrenheit should default to 32. Typing in either input should update other input field with the converted value. Easy enough.

Before I could start, I needed to create a namespace for my developer org. Which seemed weird, but apparently the name space is used to include your components in applications. For example, with a namespace of scuevo:

    <aura:application>  //I wonder if they will stick with aura or change it to lightning
<scuevo:myAuraComponent/>
</aura:application>

This seems like it would be inconvenient especially for consultants that are working in several different orgs at once; I wonder if components and applications can shared like unmanaged packages?

After namespacing my org, I opened the Developer Console (I don't believe there is any IDE support yet), and created a new Lightning Component, which appears to have 6 parts:

  • The component itself
  • A Client-Side controller for your Javascript
  • A Helper, which I guess non-controller logic goes?
  • Style for your CSS (more on this in another post)
  • Documentation
  • A Renderer (I don't know what this does)

For this simple component, I am going to just use the component and a controller.

The first thing I did was create the component with some simple inputs. Lightning includes some special tags similar to visualforce :

    <aura:component>
<aura:attribute name="celsius" type="Decimal" default="0"/>
<aura:attribute name="fahrenheit" type="Decimal" default="32"/>

<ui:inputNumber value="{!v.celsius}" label="Celsius"/>
<ui:inputNumber value="{!v.fahrenheit}" label="Fahrenheit"/>
</aura:component>

The aura attributes allow us to bind values to different tags. For those of you familiar with AngularJs, this would be similar to ng-model. Setting defaults was easy enough as well as a type. I'm not sure how to typing is enforced, as I can still type non-numbers in the input fields. It also looks like the "v." notation is used to represent an attribute value in merge fields.

So now I needed to add some controller logic, so I created a controller which is just a javascript file.

({
convertCelsius : function(component, event) {
var celTemp = component.get("v.celsius");
component.set("v.fahrenheit", (celTemp*1.8)+32);
},

convertFahrenheit : function(component, event) {
var fahTemp = component.get("v.fahrenheit");
component.set("v.celsius", (fahTemp-32)/1.8);
}
})

It appears that javascript functions have to be enclosed in a object. Doing the following won't compile:

    function aFunction(){ doSomething; }

I also updated my component to the following:

<aura:component implements="force:appHostable">
<aura:attribute name="celsius" type="Decimal" default="0"/>
<aura:attribute name="fahrenheit" type="Decimal" default="32"/>

<ui:inputNumber value="{!v.celsius}" keyup="{!c.convertCelcius}" label="Celsius"/>
<ui:inputNumber value="{!v.fahrenheit}" keyup="{!c.convertFahrenheit}" label="Fahrenheit"/>
</aura:component>

I couldn't find the documentation for all the attributes that takes and just happened to stumble upon keyup in one of the example, so if anyone has a list of those let me know. Regardless, on keyup we call the respective values and the lightning element and event itself are implicity passed to the method.

Everything seemed to work ok, but the inputs were only updating AFTER I took focus off of the input field. For example, after typing 100 in the Celsius box, the Fahrenheit box wouldn't update until I left the Celsius one. While close, it's not exactly right so I pressed on.

As the documentation didn't list the supported tag attributes, I had to dig through the source code, which is fortunately available on GitHub . I finally stumbled upon the updateOn attribute, and while I didn't know what it accepted I just tried throwing keyup into it. And it worked!

<aura:component implements="force:appHostable">
<aura:attribute name="celsius" type="Decimal" default="0"/>
<aura:attribute name="fahrenheit" type="Decimal" default="32"/>

<ui:inputNumber updateOn="keyup" value="{!v.celsius}" keyup="{!c.convertCelcius}" label="Celsius"/>
<ui:inputNumber updateOn="keyup" value="{!v.fahrenheit}" keyup="{!c.convertFahrenheit}" label="Fahrenheit"/>
</aura:component>

While completely unstyled, the Lightning component was complete, I got my Tile and I was off to another session with a dumb smirk on my face for figuring it out.

I barely scratched the surface of Lightning, but it's definitely a promising framework that will might replace some of the AngularJs in my future applications, at least in Salesforce. I still need to play with server-side actions, seeing how apps handle multiple components including the same libraries, how libraries play with components themselves and figure out what the other parts of the componnt resource bundle do that I just completely ignored. Also, the documentation leaves much to be desired, but I'm sure that will get better as time passes and this leaves beta.

Have you built any Lightning components? I'm sure they do much more than just convert temperature units so I'd love to see them!