Lightning Component Zero to Hero: Lets Get Building

, salesforcedevs, Developer, development, Force.com, Salesforce, Lightning, Lightning Components

Lets Get Building

I am a believer that the best way to learn anything is a good mixture of theory and practice. One of the biggest gripes I have with a lot of tutorials is that they tend to head too far down one route or the other. You find you get a theoretical covering that means you know exactly what everything is but not how to apply it or a very detailed example of how to apply something in a specific situation without the understanding how it can be generalised. My hope is to walk this fine line - lets see how it goes.

We have already covered some good Lightning theory in the last post and will continue to cover more details as we start to work with them. For the practical piece we are going to frame our theory around implementing a component that will enable us to view and create tasks against a record.

Yes another to do list application! How fun! And pointless.

So I know a lot of stuff has already been done around todo lists and there are doubtless a large bunch of examples around this, however the reasons todo lists are so perfect for us are as follows; firstly everyone understands the concept of a todo list and secondly we can cover off using almost all of the Lightning component framework’s features in creating a todo list, namely:

  • input and output
  • saving data
  • retrieving data
  • events
  • styling

We can also make it available for use on a Lightning Experience page meaning we can play with the documentation and design areas (something not typically covered) as well as adding a snazzy logo. (I don’t believe we will need a custom renderer in this but if I can find some way of helping us to use one I will as well - no promises though!)

The Frontend

So what do we need in a todo list application? I think the following things:

  • A list of items
  • An input area for a new item (lets say wanting a subject and a due date)

For now that is all we are going to concern ourselves with - anything extra we can add as we go on.

Below is the starting code for our component (what goes into our component or .cmp file):

<aura:component >
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
    
    <aura:attribute name="newTask" type="Task" default="{ 'sobjectType': 'Task' }" />
    <aura:attribute name="tasks" type="Object[]"/>

    <aura:iteration items="{!v.tasks}" var="item">
        {!item.Subject}, {!item.ActivityDate}<br/>
    </aura:iteration>
	
    <force:inputField aura:id="taskSubject" value="{!v.newTask.Subject}"/>
	<force:inputField aura:id="taskDate" value="{!v.newTask.ActivityDate}"/>
    
    <ui:button label="Add Task" press="{!c.addTask}" />
</aura:component>

Lets go through this code. The first line is just the opening tag to say we are creating an aura component. Why aura? Aura is the system underlying the Lightning fraemwork and so there is a lot of aura labels still around. Aura is an open source framework in Java which you can run on your own server away from Salesforce.

The next line instructs the component to do something - to handle - a particular event using the aura:handler tag. The event we are going to handle is the standard “init” - short for initialisation - event which fires when the component is loading up. We are going to call the doInit method on our controller as the action we want to take, and the value we want to pass to that function is this. A lot has been written in programming about what this is but lets here agree that this is the component we are loading. So we tell the doInit method on the controller to run with our component as a parameter when the init event occurs.

The next two items are the attributes we are going to be manipulating as our data. The first is newTask which has the type of “Task” i.e. a standard Salesforce Task record. We also set its default value to just be an empty Task record. The second attribute is the list of tasks we have to do and it has this strange Object[] data type. The square brackets [ ] indicate it is an array or a list of this type. Object is a special keyword and it means any generic type of object we can work with. This will get updated as we go forward and retrieve data from the server but for now suffices to enable us to add a list of items in code quickly.

The aura:iteration tag iterates over the list of tasks and denotes the one currently in hand for each step of the iteration to be called item and we are going to list out the Subject and ActivityDate value using the {!item.___} syntax.

Next up is some force:inputField elements for capturing the data. Firstly, notice how the tag prefix has changed from aura to force? That is because the force:inputField tag is for binding to Salesforce object (SObject) fields and having Salesforce render the correct input field - so for the Subject field on the newTask record it displays a text box and for the ActivityDate field it renders a date picker - anybody who had ever written a regular HTML UI nows how helpful this is.

The final piece is a button that has the “Add Task” label and calls the addTask method on the Lightning controller when pressed.

That’s everything for our UI for now, we will in future make this a lot prettier and easy to use but for now this will do everything we want. Before we dive into the controller and helper fiels however, there is something else I want to cover off…

V & C & Binding

The eagle eyed amongst you will have noticed in the code that when we are referring to our attributes in other elements that we have the letter v in our binding expression, when we use the controller for actions we have the lettr c in the binding expression, but for our item we have neither. What is happening here?

The notation {!xxxxx} is used by Salesforce in both Lightning and Visualforce to denote some binding to some data. When we bind we are telling Salesforce to use that data as the value, input, action or something else for the tag we are working with (or we can just output it on the component like we are doing with item). If you were to look at other component frameworks they will also have some marker system (AngularJS uses double curly braces for example) to help the framework know where to put data on the page, Salesforce have simply kept with their earlier notation of {! } to make things more consistent.

So what is v or c and why doesn’t item use it?

v is what I refer to as the view object - it is the JavaScript object that is used to hold data for display on the component. So when we bind to these attributes or pieces of data we have to refer to it as a property of the view object, so {!v.tasks} means the bind to the tasks property on the view object. The reason for this setup is that Salesforce have abstracted away a lot of helpful mechanics in the background to make displaying and managing this data easier - I can assure you that all other similar JavaScript frameworks do this but Salesforce have just labelled it up more consistently.

c refers to our component (or Lightning) controller, the JavaScript controller we create as part of the bundle. When we bind to a function on the controller using the {!c.someFunction} notation we are preparing to invoke that function when we need it.

So why does item not get prefixed with v or c? Well it is not a function in our controller so definitely would not get prefixed with c. The item variable is not an attribute of our component and so we do not prefix with v, it is simply a local variable only useful within the scope of the aura:iteration tag hence it can be vound to using just {!item}.

Controller and Helper

The controller code is posted below and is quite simple:

({
    doInit : function(component, event, helper) {
        helper.loadTasks(component);
    },
    
    addTask : function(component, event, helper) {
        helper.addTask(component);
    }
})

We have our two functions defined, doInit which runs on the component’s initialisation and calls the loadTasks method on the helper. Similarly we have our addTask function which calls the function of the same name on the helper.

Why have I moved this logic to the helper file? The logic to add a new task or load some tasks is likely to be reusable and does not directly interact with the user interface. We will be setting the value of the attributes on our view/v object but we will not be directly manipulating the UI from within those functions, hence they are moved to the helper, which is shown below:

({
    loadTasks : function(component) {
        var dt = new Date();
        var demoItems = [{Subject: 'Task1', ActivityDate: dt.toDateString()},
                         {Subject: 'Task2', ActivityDate: dt.toDateString()},
                         {Subject: 'Task3', ActivityDate: dt.toDateString()}];
        component.set("v.tasks", demoItems);
    },
    
    addTask : function(component) {
        var items = component.get("v.tasks");
        var newItem = {Subject: component.get("v.newTask.Subject"), ActivityDate: new Date(component.get("v.newTask.ActivityDate")).toDateString()}
        items.push(newItem)
        component.set("v.tasks", items);
        component.set("v.newTask", {'sobjectType': 'Task','Subject': '','ActivityDate': ''});
    }
})

Our loadTasks function here just creates an array of dummy data and assigns it to our tasks array. It does this using a special method called set on the component object we passed it. The component parameter we passed into the function is the JavaScript object for our component (which was {!this} in our init binding at the start of our component). The component object has a v property which is our view object and we use the set method to set the value of v.tasks to be our dummy task list. Set does some more clever things in the background but put simply enables us to set values on properties. You will end up using it a lot.

In our addTask function we use the inverse function of set which is get and retrieves the value of a property on the component for us. In this case we get our existing list of tasks and put it in a variable called items. We then create a newItem where we mirror the notation in our loadTasks function and set the values to be those input on our input fields. Finally we push that value onto our array and set the taks list to be our updated array and clear the values from our newTask record.

In Action

If you put all this in a component you will need to add it to a Lightning app for it to be visible to you for simple test purposes (again, we will update this going forward). I created an app called “DemoApp” for my testing and added my component called “ToDoList” as follows:

<aura:application >
    <c:ToDoList ></c:ToDoList>
</aura:application>

You should be able to preview and see it working! You can fill out those fields and add new tasks as well with the UI updating instantly.

Next Time

Next time we are going to do some styling to make this prettier and add a complete function to make it easy for us to mark items as complete. After that we will look towards taking our local version and adding the abiity to load real task data into the system.

Share on Twitter, Facebook, Google+
Prev Next