Build a Suggestion Box App with Lightning Components

Table of Content

  1. Introduction
  2. Add a Custom Domain to Your Org with My Domain
  3. Create a Server-side Apex Controller Class
  4. Create the SuggestionBoxApp Application
  5. Create the SuggestionBoxCreate Component
  6. Create the SKChange Event and SearchBar Component
  7. Create the SuggestionList Component
  8. Create the SuggestionDetails Component
  9. Summary

Introduction

In this project, you learn how to build a Lightning Application on App Cloud from start to finish.If you’re new to App Cloud, the goal is to introduce you to the basics of app building together with introduction to the new lightning platform and basics to develop application using lightning components. If you’re familiar with the App Cloud Admin features—managing users and security, customizing standard objects, and so on—the goal is to apply those skills to developing new application and learn how to extend the functionality of these applications using lightning.

You need a Developer Edition org to complete this project. If you don’t have one, you can sign up here.

You will build a Suggestion Box Lightning Application that allows employees to submit suggestions, search for existing suggestions and vote for them. All of this with the following steps:

  1. Install the pre-created building blocks of the Suggestion Box App by clicking here and here These packages include the app definition, data model, validation rules, process and reports and dashboard which together form the basic Suggestion box Application. Steps to install an unmanaged package are detailed here. You can install this app for Admins only for now.

  2. Extend this application using Lightning components to design a stand-alone Suggestion Box Application which will look something like this:

Each rectangle in this image represents a lightning component:

  1. Displays the “add suggestion” functionality
  2. Displays the “search suggestion” functionality
  3. Displays the “results” of the search functionality
  4. Displays the “details of the selected record” in the search functionality
  5. “Suggeston Box” Lightning Application

Let’s begin with exploring our prebuilt Suggestion Box App which was installed using the package.

All eyes on the screen!

Now, that we know and understand how we can build a basic application using point-and-click, let us now extend this app using lightning components.The UI of the Application we will create will resemble the Lightning Experience UI as we will make use of Salesforce Lightning Design System.

Add a Custom Domain to Your Org with My Domain

To use Lightning Components, your organization needs to have a custom domain configured using My Domain.

To provide world class security for apps, we’re requiring that all users of Lightning Components use My Domain, just as we do for other advanced features, such as Salesforce Identity. If you want to use Lightning Components in Lightning tabs, Lightning Pages, or as standalone apps, you must enable My Domain in your org.

Enable My Domain in Your Org

Set up a custom domain with the Salesforce My Domain feature to put your Lightning Components to work. If you already have My Domain enabled in your Developer org, you can skip this section and the next one.

  1. From Setup, go to My Domain
  2. Enter the subdomain name you want to use within the sample URL. For example, a company called Universal Containers wants to use the subdomain universalcontainers. The company’s login URL would be https://universalcontainers.my.salesforce.com/. Your name can include up to 40 letters, numbers, and hyphens.
  3. Click Check Availability. If your name is already taken, choose a different one
  4. Click Terms and Conditions to review your agreement, then select the checkbox
  5. Click Register Domain

You receive an email when your domain name is ready for testing. It can take up to 3 minutes.

Roll Out My Domain to Your Org

After you set up your domain name, test it and then roll it out to your org. Even though you don’t have any users to deploy it to in your DE org, you must still roll out My Domain to make your custom Lightning components available in Lightning Pages, in the Lightning App Builder, and for standalone apps.

  1. Test your domain login. From Setup, go to My Domain, then Click here to login. Or, log out of your DE org and log in to Salesforce using your custom domain name. You can click the login link in the activation email you received.
  2. Test the new domain name by clicking tabs and links. All pages now show your new domain name.
  3. To roll out the new domain name to your organization, from Setup, go to My Domain , Click on Deploy to Users then select OK

Create a Server-side Apex Controller Class

Create a class to access data from Suggestion custom object:

  1. In your DE environment, click Your Name | Developer Console
  2. Select File | New | Apex Class
  3. For the class name, enter SuggestionController and then click OK
  4. Replace the code with the following:
public class SuggestionController {

  	@AuraEnabled
	public static List<Suggestion__c> getSuggestions() {
		return [SELECT id, Name, Status__c, Suggestion_Category__c, Suggestion_Description__c,	Implemented_Date__c, createdDate 
			FROM Suggestion__c 
			ORDER BY createdDate DESC];
	  }
    
    @AuraEnabled
    public static Suggestion__c saveSuggestion(Suggestion__c suggestion) {
        upsert suggestion;
        return suggestion;
    }
    
    @AuraEnabled
    public static List<Suggestion__c> findAll() {
        return [SELECT id, name, Suggestion_Description__c, Vote_up__c FROM Suggestion__c LIMIT 50];
    }
    
    @AuraEnabled
    public static List<Suggestion__c> findByName(String searchKey) {
        String name = '%' + searchKey + '%';
        return [SELECT id, name, Suggestion_Description__c, Vote_up__c FROM Suggestion__c WHERE name LIKE :name LIMIT 50];
    }  
   
    @AuraEnabled
    public static Suggestion__c findById(String suggestionId) {
        return [SELECT id, name, Status__c, Suggestion_Category__c, Suggestion_Description__c,Vote_up__c
                    FROM Suggestion__c WHERE Id = :suggestionId];
    }
    
    @AuraEnabled
    public static Suggestion__c voteSuggestion(String suggestionId) {
        Suggestion__c s = new Suggestion__c();
        s=[SELECT id, name, Status__c, Suggestion_Category__c, Suggestion_Description__c,Vote_up__c
                    FROM Suggestion__c WHERE Id =:suggestionId];
        
        s.Vote_up__c = s.Vote_up__c + 1;
        upsert s;
        return s;
    } 
} 

@AuraEnabled enables client and server-side access to the controller method. Select File | Save.

Create the SuggestionBoxApp Application

This application holds all the components we will create in th next steps together to make it a stand-alone application.

  1. In the Developer Console, select File | New | Lightning Application
  2. For the component name, enter SuggestionBoxApp and then click Submit
  3. Replace the code with the following:
<aura:application>
    <ltng:require styles="/resource/slds/assets/styles/salesforce-lightning-design-system-ltng.css" />
    <div class="salesforce slds">
        <div class="slds-grid slds-wrap slds-grid--pull-padded">
            <div class="slds-col--padded slds-size--1-of-1 slds-medium-size--1-of-1 slds-large-size--1-of-6"></div>
            <div class="slds-col--padded slds-size--1-of-1 slds-medium-size--1-of-1 slds-large-size--4-of-6">
                <h3 class="slds-section-title--divider  slds-text-align--center textsize">SUGGESTION BOX APPLICATION</h3>
            </div>
            <div class="slds-col--padded slds-size--1-of-1 slds-medium-size--1-of-1 slds-large-size--1-of-6"></div>
            <div class="slds-col--padded slds-size--1-of-1 slds-medium-size--1-of-2 slds-large-size--1-of-6"></div>
            <div class="slds-col--padded slds-size--1-of-1 slds-medium-size--1-of-2 slds-large-size--4-of-6">
                <div class="slds-grid">
                    <div class="slds-col">
                       <!-- <c:SuggestionBoxCreate /> to be uncommented after component creation -->
                       <!-- <c:SearchBar /> to be uncommented after component creation -->
                    </div>
                </div>
                <div class="slds-grid slds-grid--pull-padded">
                    <div class="slds-col--padded">
                       <!-- <c:SuggestionList /> to be uncommented after component creation -->
                    </div>
                    <div class="slds-col--padded">
                       <!-- <c:SuggestionDetails /> to be uncommented after component creation -->
                    </div>
                </div>
            </div>
            <div class="slds-col--padded slds-size--1-of-1 slds-medium-size--1-of-2 slds-large-size--1-of-6"></div>
            <div class="slds-col--padded slds-size--1-of-1 slds-medium-size--1-of-1 slds-large-size--1-of-6"></div>
            <div class="slds-col--padded slds-size--1-of-1 slds-medium-size--1-of-1 slds-large-size--4-of-6">
                <h3 class="slds-section-title--divider  slds-text-align--center textsize">@created by Salesforce Developer Relations Team</h3>
            </div>
            <div class="slds-col--padded slds-size--1-of-1 slds-medium-size--1-of-1 slds-large-size--1-of-6"></div>
        </div>
    </div>
</aura:application>

You can see how the application looks by clicking on the Preview button, the first button in the application bundle.

Code Highlights:

  • This application uses lightning design system guidelines to create the UI as explained here

Create the SuggestionBoxCreate Component

This component will implement the Add Suggestion functionality.

A lightning component is a combination of markup, JavaScript, and CSS. You first create a component bundle.

  1. In the Developer Console, select File | New | Lightning Component
  2. For the component name, enter SuggestionBoxCreate and then click Submit
  3. Replace the code with the following:
<aura:component controller="SuggestionController" implements="flexipage:availableForAllPageTypes">
   <ltng:require styles="{!$Resource.slds + 'assets/styles/salesforce-lightning-design-system-vf.css'}" />
   <aura:attribute name="suggestions" type="Suggestion__c[]" />
   <aura:attribute name="newSuggestion" type="Suggestion__c"
      default="{ 'sobjectType': 'Suggestion__c',
      'Name': '',
      'Status__c': '',
      'Suggestion_Category__c': '',
      'Suggestion_Description__c': ''
      }"></aura:attribute>
   <div class="container">
      <h1>
         Add Suggestions
         <div style="margin-left: 0; height: 30px; float: right; margin-top: -3px; margin-right: 0; auto; vertical-align: inherit;">
            <ui:button aura:id="addbutton" label="New" labelClass="assistiveText" class="myButton" press="{!c.addNew}" />
         </div>
      </h1>
   </div>
   <!-- Input Form using components -->
   <div aura:id="formbox" class="myboxhidden">
      <form>
         <fieldset>
            <ui:inputText aura:id="sugname" label="Suggestion Name"
               class="form-control"
               value="{!v.newSuggestion.Name}"
               placeholder="Suggestion Name" required="true"/>
            <ui:inputSelect aura:id="category" label="Suggestion Category"
               class="cExpenseForm form-control"
               value="{!v.newSuggestion.Suggestion_Category__c}"
               required="true" >
               <ui:inputSelectOption text="Customer Service" value="Customer Service"/>
               <ui:inputSelectOption text="Employee Services" value="Employee Services"/>
               <ui:inputSelectOption text="Facilities/ IT" value="Facilities/ IT" />
               <ui:inputSelectOption text="Kitchen Snacks" value="Implemented"/>
               <ui:inputSelectOption text="Others" value="Implemented"/>
            </ui:inputSelect>
            <ui:inputText aura:id="description" label="Suggestion Description"
               class="cExpenseForm form-control"
               value="{!v.newSuggestion.Suggestion_Description__c}"
               placeholder="Describe your suggestion here" />
            <ui:button label="Submit" press="{!c.createSuggestion}" />
         </fieldset>
      </form>
   </div>
</aura:component>
  1. Select File | Save
  2. In the button panel on the right, click Controller
  3. Replace the code with the following:
  ({
   addNew: function(component, event, helper) 
    			{
                var el = component.find('formbox');
                if ($A.util.hasClass(el.getElement(), 'myboxhidden')) 
                {
                helper.showInput(component);
				} 
                    else {
				helper.hideInput(component);
						 }
				},
                
    createSuggestion: function(component, event, helper) 
    			{
                var newSuggestion = component.get("v.newSuggestion");
                helper.createSuggestion(component, newSuggestion);
				}
}) 
  1. Select File | Save
  2. In the button panel on the right, click Helper
  3. Replace the code with the following:
({
    showInput: function(component) {
        var el = component.find('formbox');
        $A.util.removeClass(el.getElement(), 'myboxhidden');
        $A.util.addClass(el.getElement(), 'mybox');
    },

    hideInput: function(component) {
        var el = component.find('formbox');
        $A.util.addClass(el.getElement(), 'myboxhidden');
    },

    createSuggestion: function(component, suggestion) {
        this.upsertSuggestion(component, suggestion, function(a) {
            var suggestions = component.get("v.suggestions");
            suggestions.unshift(a.getReturnValue());
            component.set("v.suggestions", suggestions);
            this.hideInput(component);
        });
    },
    upsertSuggestion: function(component, suggestion, callback) {
        var action = component.get("c.saveSuggestion");
        action.setParams({
            "suggestion": suggestion
        });
        if (callback) {
            action.setCallback(this, callback);
        }
        $A.enqueueAction(action);
    }

})
  1. Select File | Save
  2. In the button panel on the right, click Style
  3. Replace the code with the following:
.THIS h3 {
	margin: 0px;
}
.THIS h1 {
	font-size: 24pt;
	margin-top: 5px;
	margin-bottom: 5px;
	margin-left: 5px;
	margin-right: 5px;
    height: 35px;
    
}

.THIS.container {
	margin: 5px;
	border: 1px solid black;
	border-radius: 1px;
	background-color: rgb(200, 198, 198);
    font-size: 18pt;
}

.THIS .form-control {
    display: block;
    width: 100%;
    height: 34px;
    padding: 6px 14px;
    font-size: 14px;
    line-height: 1.42857143;
    color: #000000;
    background-color: #ffffff;
    background-image: none;
    border: 1px solid #cfd0d2;
    border-radius: 4px;
    -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
    box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
    -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
    -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
    transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
}

.THIS .myButton {
	width: 35px;
	background-image: url(/resource/plusbutton);
	background-repeat: no-repeat;
	height: 35px;
	background-size: contain;
	/*margin-left: -50px;*/
	border-style: none;
	background-color: transparent;
}

.THIS .img {
	background: url(/resource/plusbutton/) no-repeat;
	width:50px;
	height:25px;
}

.THIS.mybox {
  /*display: block;*/
  opacity: 1;
  margin-left: 5px;
  margin-bottom: 5px;
  margin-right: 5px;
  transform: scale(1, 1);
  transition-property: transform, height;
  transition-duration: 1s, 1s;
}

.THIS.myboxhidden {
  /*display: none;*/
  transform: scale(0,0);
  height: 0;
  /*opacity: 0;*/
  transition-property: transform, height;
  transition-duration: 1s, 1.2s;
}
  1. Open the SuggestionBoxApp Application and replace the below
<!-- <c:SuggestionBoxCreate /> to be uncommented after component creation -->   

with

 <c:SuggestionBoxCreate />     

You can see how the application looks by clicking on the Preview button, the first button in the application bundle.

Code highlights:

  • Lightning components can include regular HTML markup and other Lightning components
  • The Server-side Apex Controller has methods which will be used by components to access and modify records in the database
  • The controller in the Component bundle has javascript methods which use the component attributes and invoke server side controller method to process data. CreateSuggestion is one such method which invokes savesuggestion method in the SuggestionController apex class
  • The newSuggestion attribute is defined to hold the new suggestion that will be created by employee via the form.
  • {!v.newSuggestion.Name} is the Lightning data binding notation to take the name field as input from the user
  • .THIS in the CSS symbolises that the css written in the component bundle only applies to this specific component UI

Create the SKChange Event and SearchBar Component

We are creating two components namely the SearchBar and SuggestionList which need to communicate with each other to implement the search functionality.When employee types the searchkey in the searchbar, the Suggestionlist component should be updated with relevant suggestions.This communication will happen using the Lightning Event.

  1. In the Developer Console, select File | New | Lightning Event
  2. For the event name, enter SKChange and then click Submit
  3. Replace the code with the following:
<aura:event type="APPLICATION">
    <aura:attribute name="searchKey" type="String"/>
</aura:event>

Code highlights:

  • This event holds a single attribute named searchkey

Creating the SearchBar Component

This component will implement the Search Suggestion functionality.

  1. In the Developer Console, select File | New | Lightning Component
  2. For the component name, enter SearchBar and then click Submit
  3. Replace the code with the following:
<aura:component implements="flexipage:availableForAllPageTypes" >
   <ltng:require styles="{!$Resource.slds + 'assets/styles/salesforce-lightning-design-system-vf.css'}" />
   <aura:registerEvent name="SKChange" type="c:SKChange"/>
   <div class="slds-form-element">
      <div class="slds-form-element__control">
         <input id="text-input-01" class="slds-input textfont" type="text" onkeyup="{!c.searchKeyChange}" placeholder="Search for Suggestions" />
      </div>
   </div>
</aura:component>
  1. Select File | Save
  2. In the button panel on the right, click Controller
  3. Replace the code with the following:
({
    searchKeyChange: function(component, event, helper) {
        var myEvent = $A.get("e.c:SKChange");
        myEvent.setParams({"searchKey": event.target.value});
        myEvent.fire();
    }
})
  1. Select File | Save
  2. In the button panel on the right, click Style
  3. Replace the code with the following:
.THIS .textfont{
    font-family:'Salesforce Sans', Arial, sans-serif;   
    font-size: 15pt;
}
  1. Select File | Save
  2. Open the SuggestionBoxApp Application and replace the below:
 <!-- <c:SearchBar /> to be uncommented after component creation -->  

with

  <c:SearchBar />     

You can see how the application looks by clicking on the Preview button, the first button in the application bundle.

Code highlights:

  • The SearchBar component has a single input field where employee will type the searchkey and each key entered in this field will trigger the searchKeyChange client-side controller function
  • The searchKeyChange takes the event and sets the event parameter searchKey as the input field’s value
  • Once set, it fires the event for the registered listners can catch it

Create the SuggestionList Component

This component will display the list of Suggestions based on the searchKey.

  1. In the Developer Console, select File | New | Lightning Component
  2. For the component name, enter SuggestionList and then click Submit
  3. Replace the code with the following:
<aura:component controller="SuggestionController" implements="flexipage:availableForAllPageTypes">
   <ltng:require styles="{!$Resource.slds +'assets/styles/salesforce-lightning-design-system-vf.css'}" />
   <aura:attribute name="suggestions" type="Suggestion__c[]"/>
   <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
   <aura:handler event="c:SKChange" action="{!c.searchKeyChange}" />
   <div class=" salesforce slds">
      <ul class="slds-has-dividers--around-space">
         <aura:iteration items="{!v.suggestions}" var="suggestion">
            <li class="slds-item">
               <div class="slds-tile slds-tile--board">
                  <h3 class="slds-truncate" ><a href="{! '#suggestion/' + suggestion.Id }">Name: {!suggestion.Name}</a></h3>
                  <div class="slds-tile__detail slds-text-body--small">
                     <p class="slds-text-heading--medium">Description : {!suggestion.Suggestion_Description__c}</p>
                  </div>
               </div>
            </li>
         </aura:iteration>
      </ul>
   </div>
</aura:component>
  1. Select File | Save
  2. In the button panel on the right, click Controller
  3. Replace the code with the following:
({
    doInit : function(component, event) {
        var action = component.get("c.findAll");
        action.setCallback(this, function(a) {
            component.set("v.suggestions", a.getReturnValue());
        });
        $A.enqueueAction(action);
    },
    
    searchKeyChange: function(component, event) {
    var searchKey = event.getParam("searchKey");
    var action = component.get("c.findByName");
    action.setParams({
      "searchKey": searchKey
    });
    action.setCallback(this, function(a) {
        component.set("v.suggestions", a.getReturnValue());
    });
    $A.enqueueAction(action);
	}
    
})
  1. Open the SuggestionBoxApp Application and replace the below
 <!-- <c:SuggestionList /> to be uncommented after component creation -->  

with

  <c:SuggestionList />     

You can see how the application looks by clicking on the Preview button, the first button in the application bundle.

Code highlights:

  • The controller assigned to the component refers to the server-side controller SuggestionController
  • This component catches the SKChange Event and handles it with the <aura:handler> tag triggering the client-side controller function searchKeyChange
  • The suggestions attribute is defined to hold the list of suggestion objects returned from the server
  • The init handler is defined to execute some code when the component is initialized
  • <aura:iteration> is used to iterate through the list of suggestions and create an <li> for each suggestion
  • The <a href="{! '#suggestion/' + suggestion.Id }"> anchor tag around the suggestion data is defined to set the page hashtag to #suggestion/ followed by the suggestion id. The SuggestionDetails component will use this hashtag to display suggestion details every time an employee selects a suggestion from the list
  • We get the value of the searchKey and then invoke findByName() method in the SuggestionController Apex class
  • A callback is used here as the call to the server is an asynchronous call. When this call returns some value, we assign the list of suggestions returned by findByName() to the component’s suggestions attribute.

Create the SuggestionDetails Component

This component will display the details of the suggestion selected by the employee from the Suggestionlist Component.

  1. In the Developer Console, select File | New | Lightning Component
  2. For the component name, enter SuggestionDetails and then click Submit
  3. Replace the code with the following:
<aura:component controller="SuggestionController" implements="flexipage:availableForAllPageTypes">
   <ltng:require styles="{!$Resource.slds}" />
   <aura:attribute name="suggestion" type="Suggestion__c"/>
   <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
   <aura:handler event="aura:locationChange" action="{!c.locationChange}"/>
   <aura:if isTrue="{! v.suggestion.Name !=null }">
      <div class="details">
         <ul class="slds-has-dividers--around-space">
            <li class="slds-item">
               <div class="slds-tile slds-tile--board">
                  <h3 class="slds-truncate"><a href="javascript:void(0);">
                     Suggestion Details
                     </a>
                  </h3>
                  <div class="slds-tile__detail slds-text-body--small">
                     <p class="slds-text-heading--medium">
                        {!v.suggestion.Name} 
                     </p>
                     <p class="slds-truncate"><a href="javascript:void(0);">
                        {!v.suggestion.Status__c} 
                        </a>
                     </p>
                     <p class="slds-truncate">
                        {!v.suggestion.Suggestion_Category__c} 
                     </p>
                     <p class="slds-truncate"><a href="javascript:void(0);">
                        {!v.suggestion.Suggestion_Description__c} </a>
                     </p>
                     <p class="slds-truncate">
                        {!v.suggestion.Vote_up__c}
                        <aura:if isTrue="{! v.suggestion.Name !=null }"> Votes
                        </aura:if>
                     </p>
                     <p class="slds-truncate">
                        <a href="javascript:void(0);">
                           <aura:if isTrue="{! v.suggestion.Name !=null }">
                              <button class=".slds-button--neutral" type="button" onclick="{!c.voteup}" >Vote up</button>
                           </aura:if>
                        </a>
                     </p>
                  </div>
               </div>
            </li>
         </ul>
      </div>
   </aura:if>
</aura:component>
  1. Select File | Save
  2. In the button panel on the right, click Controller
  3. Replace the code with the following:
({
    locationChange: function(component, event, helper) {
        var token = event.getParam("token");
        if (token != null) {
            if (token.indexOf('suggestion/') === 0) {
                var suggestionId = token.substr(token.indexOf('/') + 1);
                var action = component.get("c.findById");
                action.setParams({
                    "suggestionId": suggestionId
                });
                action.setCallback(this, function(a) {
                    component.set("v.suggestion", a.getReturnValue());
                });
                $A.enqueueAction(action);
            }
        }
    },


    doInit: function(component, event) {
        var token = event.getParam("token");
    },

    voteup: function(component, event) {

        var suggestionId = event.target.id;
        var action = component.get("c.voteSuggestion");
        action.setParams({
            "suggestionId": component.get("v.suggestion.Id")
        });
        action.setCallback(this, function(a) {
            component.set("v.suggestion", a.getReturnValue());
        });
        $A.enqueueAction(action);
    }
})
  1. Select File | Save
  2. Open the SuggestionBoxApp Application and replace the below
 <!-- <c:SuggestionDetails /> to be uncommented after component creation -->  

with

  <c:SuggestionDetails />     

You can see how the FINAL application looks by clicking on the Preview button, the first button in the application bundle.

Code Highlights:

  • In the SuggestionList component we created, we wrapped each suggestion in the list with a <a href="{! '#suggestion/' + suggestion.Id }"> anchor tag that sets the page hashtag to #suggestion/ followed by the suggestion id of the clicked suggestion. In this component, the locationChange handler is defined to listen to hashtag changes, and execute the controller’s locationChange() when it happens. The locationChange() function implemented in the next step retrieves and displays the selected suggestion
  • The button labeled as Vote Up is used by employees to vote up a suggestion.The button when clicked triggers the voteup function in the client-side controller
  • The locationChange function gets the new value of the hashtag which it then parses to extract the suggestion id and invokes the findById() method in the Apex controller SuggestionController. When the asynchronous call returns, it assigns the suggestion returned by findById() to the component’s suggestion attribute.
  • The voteup function calls the voteSuggestion method in the server-side controller and passes the suggestion id as the method parameter.When the asynchronous call returns, it assigns the suggestion returned by voteupSuggestion() to the component’s suggestion attribute thus updating the vote count

Summary

Congratulations! You’ve become a Lightning application developer! You created and wired up events between multiple Lightning components. You created a suggestion box component that is built with other components. You have created and used a server-side controller for pulling data out of Salesforce as well as several client-side components to handle user interaction.

These building blocks are used for creating every kind of Lighnting application!