Streams of Lightning: Part Three

As you may or may not know, I was out in San Francisco last week attending my first MVP Summit. For this reason, I did not post part three of my current lightning tutorial. <sarcasm>Since you’re no doubt waiting directly on the edge of your seat<sarcasm>, lets get right back to it.

Last week we left off with a component that was just a tiny bit more flexible than a simple “Hello World” type of component. We were able to add our component to the lightning app builder and configure said component to display the current active poll question. Today we will move on to having this component nest a secondary component that will be responsible for displaying our poll’s options as buttons on the screen. For this, we need to create a brand new custom component, so we’ll begin there.

In the developer console click File->New->Lightning Component. We will call this component “PollItemOption.” Once again we will get the familiar skeleton code, but we’re going to replace it with the following:

<aura:component >

    <aura:attribute name="pollOption" type="Poll_Option__c"/>
    <aura:attribute name="pollOptionId" type="String" default="{!v.pollOption.Id}"/>
    <div style="border:1px solid black;margin:5px;padding:10px;text-align:center;border-radius:5px">
        <ui:button aura:id="voteButton" label="{!v.pollOption.Name}" />
        <div style="float:right" class="findme" id="{!v.pollOption.Id}">


For this component, we are creating a place holder for the Poll Option object itself (pollOption attribute). Remember that we will be using this component “inside” of our Poll Question component that we’ve been working with. That parent component will be passing a Poll Option object to this one. In our case, the Poll Question component will loop over the Options that belong to it and pass them to this component for rendering. We will also likely need the ID of the Option we are working with for updates, etc so we’ll create a place to store that ID as well (pollOptionId attribute).

Next we add some HTML and styling to our component. We will be displaying the poll options as clickable buttons that our users will tap in order to vote for them. I’m wrapping these ui:button pieces in an HTML div for more control over styling. (Once again, I must point out that I am doing this “wrong” during development as style should go in the CSS file that belongs to the component — we’ll get there, but when I’m coding, I like my styles right where I’m working, its just a preference for me). Inside that div we have an instance of ui:button, the label of that button will be the Poll Option’s name field, referred to with our shorthand for accessing attributes in our view: {!v.pollOption.Name}. We can also tell that button what function to call when it is pressed (but we will do that in part 4 next week).

I follow this button up with some HTML markup to assist in styling and then I close it up.

This component, though it will have zero/broken functionality can now be rendered within our parent component, so lets just wire it up briefly so we can track our progress. Open up the Poll Question component that we created in part one. (If you don’t already have it open you will need to go to File->Open Lightning Resources and expand the appropriate folder, highlight the individual pieces and click on the Open Selected button at the bottom of that dialog window).

Now let’s add an iteration over our Poll Options from within our PollQuestion component and have it pass each option to our newest component. Replace the PollQuestion component code with this code (really you only need to add the aura:iteration tag and its contents):

<aura:component implements="flexipage:availableForAllPageTypes"  controller="PollController" >

    <aura:attribute name="pollQuestion" type="Poll_Question__c"/>
    <aura:attribute name="options" type="Poll_Option__c[]"/>
    <aura:attribute name="title" type="String" />
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />

    <h1 style="text-align:center">{!v.title}</h1>
    <p style="padding:10px;">{!v.pollQuestion.Name}</p>
    <aura:iteration var="option" items="{!v.pollQuestion.Poll_Options__r}">
        <c:PollItemOption pollOption="{!option}" />


What we’ve added here is the bit called an aura:iteration. It’s how we loop over collections inside lightning components. You specify the variable that you will be using for each iteration and the items over which to be iterated. In this case our variable is called “option” and our items are our poll options that we retrieve from the pollQuestion (!v.pollQuestion.Poll_Options__r} — we retrieved them in our PollController). Secondly, inside of this iteration we are telling this component to use our PollItemOption component that we just created to render each poll option (<c:PollItemOption pollOption=”{!option}” />). Here the “c:PollItemOption” means we are loading a component called “PollItemOption.” That component also has an attribute called “pollOption” that is expecting a Poll_Option object. So we pass our “option” variable in using pollOption=”{!option}”

If you load up your lightning app in Salesforce1 now, you should see our Current Poll application displaying the question and each option rendered as a button. If you’re following along, from last week we should see something similar to the screenshot below. (NOTE: Your titles will be different since I am re-writing my original app for the blog to help me keep track, and you likely won’t have any vote numbers showing up since we’ve not voted for anything yet):

Screen Shot 2015-05-19 at 9.53.08 PM

Things are starting to look a tad more useful. Next week we will add the necessary logic to allow voting on each item, followed by adding in some functionality to wire in the streaming api so that you can watch the votes increase as users vote.

If you happen to be in the Milwaukee area on Thursday, May 21st (I know its short notice) I will be demoing this application complete with streaming at the Wisconsin User Group meeting at: 250 E Juneau Ave Milwaukee, WI. The meeting starts at 11:30am. Stop on by if you find the time.