Lightning Component Best Practices

Posted on Updated on

Hi All,

In this article, I will tell you the best practices for Lightning Components, Lightning component bundle and Events.

Lightning Component

Lightning is all about components. You can build applications by assembling components created by you and other developers. A component can contain other components, as well as HTML, CSS, JavaScript, or any other Web-enabled code. This enables you to build apps with sophisticated UIs. We should always keep in mind Lightning Component’s modular approach while creating a Lightning App. It is always a best practice to use component based developement approach. Following are the benifits of component based approach.

  1. Increases
    a. Developer Productivity
    b. Feature availablity
    c. Application Scaliblity
  2. Decreases
    a. Application Complexity
    b. Time to Delivery
    c. Overall Cost

Lightning Component Bundle

Each Lightning Component is made up of a markup, JavaScript controller, a Helper, a Renderer and more(Component Bundle).

final00001

Controller

  1. Use Controllers to listen to user events and other events like Component Event, Appliction Event.
  2. Delegate your business logic to helper methods.
  3. Do not trigger DML operation on component initializaton. If you are doing DML in init(), you are creating a CSRF(Cross-Site Request Forgery).
  4. Do not modify DOM in Controller. If you modify DOM in Controller it will call renderer method which will end in no result.

Helper

Always write your business logic in helper functions because

  1. Helper functions may be called from any other javascript in the component bundle.
  2. Whenever a component runs Lightning Framework creates an instance of the Controller, an instance of the Renderer for each component but creates only one copy of the Helper and passes the reference of the Helper into every Controller instance and every Renderer instance. Below picture will make you understand this well.

final00002

Since Helper is shared across everything, it allows us to share and keep logic across of Controllers and Renderers in one place. It also helps us keep logic within Controllers and Renderers lean. Anytime you need to call one controller function from another controller function, move that logic to Helper.

Renderer

  1. Use Renderer whenever you want to customize default rendering, rerendering, afterrendering and unrendering behaviour for a component.
  2. Do not fire an event in renderer, firing an event in a renderer can cause an infinite rendering loop.
  3. If you need to directly manipulate DOM elements in your component, you should do it in the component’s renderer.

Events

  1. Always use events to implement communication between components.
  2. Always try to use a component event instead of an application event, if possible. Component events can only be handled by components above them in the containment hierarchy so their usage is more localized to the components that need to know about them. Below picture will make you understand better about component event.final00003
  3. Application events are best used for something that should be handled at the application level, such as          navigating to a specific record.appevent
  4. It’s a good practice to handle low-level events, such as a click, in your event handler and refire them as higher-level events, such as an approvalChange event or whatever is appropriate for your business logic.
  5. If you have a large number of handler component instances listening for an event, it may be better to identify a dispatcher component to listen for the event. The dispatcher component can perform some logic to decide which component instances should receive further information and fire another component or application event targeted at those component instances.
  6. Do not use onclick and ontouchend events in a component. The framework translates touch-tap events into clicks and activates any onclick handlers that are present.

That’s it for now I will come with more details in upcoming posts. 🙂

 

 

Visualforce vs Lightning

Posted on Updated on

Hi

There are lots of questions in the mind of Salesforce developers regarding Lightning but the question which comes in every Salesforce developer’s mind is, will Lightning replace Visualforce?

You will be able to answer this question after exploring the Lightning Experience and VisualForce.

vfvslightning

Lightning Experience is not finished yet. There is plenty of work for developers to do just  building out the basic Salesforce application. Many things are working great, some things are working well in “Beta”. As it is in “beta” version  there are a number of things we just haven’t gotten to yet.

We are living in a multi device world where users are expecting highly interactive and immersive experiences literally at their fingertips. Companies like Google, Facebook are making user experience highly interactive using isolated components. Online forms now come with immediate error feedback when users enter invalid data. This interactivity is no longer a novelty, it’s the norm.

So what does this mean for us?

The Visualforce framework provides a robust set of tags that are resolved at the server-side and that work alongside standard or custom controllers to make database and other operations simple to implement. This is a page-centric web application model. It’s great for basic functionality, but it’s challenging to deliver the new, more dynamic experience that users expect. Fundamentally, this is because it relies on the server to generate a new page every time you interact with the application.

Lightning components are part of the new Salesforce user interface framework for developing dynamic web applications for desktop and mobile devices. They use JavaScript at the client-side and Apex at the server-side to provide the data and business logic. To deliver a more interactive experience, you need help from JavaScript on the client-side. In this new app-centric model, JavaScript is used to create, modify, transform, and animate the user interface rather than completely replacing it a page at a time. This model is exciting, interactive, and fluid.

Both the page-centric and app-centric models have their own advantages and both are here to stay. Combining the models lets applications deliver the right type of experience for the right use case.

Let’s explore the differences between Lightning and Visualforce.

Visualforce

UI Generation

  • Server-Side

Workflow

  1. User requests a page
  2. The server executes the page’s underlying code and sends the resulting HTML to the browser
  3. The browser displays the HTML
  4. When the user interacts with the page, return to step one.

 Advantages

  1. Tried and true model
  2. Easy to implement for greater productivity
  3. Naturally splits large applications into small, manageable pages
  4. Has built-in metadata integration

 Disadvantages

  1. Limited interactivity (aside from added JavaScript functionality)
  2. Higher latency

 Lightning

 UI Generation

  •  Client-Side

 Workflow

  1. The user requests an application or a component
  2. The application or component bundle is returned to the client
  3. The browser loads the bundle
  4. The JavaScript application generates the UI
  5. When the user interacts with the page, the JavaScript application modifies the user interface as needed (return to previous step)

Advantages

  1. Enables highly interactive and immersive user experiences
  2. Aligns with Salesforce user interface strategy
  3. Built on metadata from the foundation, providing an integrated developer experience
  4. The Developer Console supports Lightning components, so there’s an integrated developer experience

Disadvantages

  1. Higher learning curve compared to Visualforce
  2. Higher complexity than Visualforce—you’re building an application, not a page
  3. Since Lightning components are new, there are still some features that aren’t supported
  4. There are a limited number of out-of-the-box components

You have gone through pros and cons of Lightning and Visualforce now you have to decide which tool you should use.

Here are some guidelines to help you decide-which tool you should use and when.

When you should use Lightning

  • If you are developing for Salesforce1 Mobile Application you should use Lightning as visualforce characteristics, especially the page-centric orientation, can be a poor match for mobile apps with limited, high-latency network connections and limited compute resources. Lightning components, by contrast, was designed specifically to handle this context.
  • If you are building an interactive experience with JavaScript to meet user experience requirements you should use Lightning.
  • If you are enabling non-developers to build apps by assembling standard or custom components you should use Lightning App Builder and Lightning components for custom components. Use Visualforce if the required components aren’t yet available.
  • If you are adding user interface element for example, say you want to add a tab to a record home. This task is a simple drag-and-drop in Lightning App Builder.
  • If you are building a Community for Customers you should use Community Builder to create a Lightning-based community site leveraging Lightning components.
  • If you are committed to invest in latest technology you should start using Lightning Components.
  • If you are starting a brand new project you should use Lightning Components. If you’re not familiar with them, there’s no better time than now to learn!

Continue using Visualforce

  • If you are building a page-centric experience with limited Client-Side logic use Visualforce.
  • If you are committed to Javascript Framework such as AngularJS or React continue using Visualforce.
  • If you are building an interactive experience with Javascript and you need third party Framework you should use Visualforce as a container for third party Framework.
  • If you are building a community for partners continue using Visualforce in Salesforce Classic. Explore using Lightning components with Lightning components for Visualforce.
  • If you are exposing a Public-Facing Unauthenticated Website continue using Visualforce. Lightning components don’t support an anonymous (unauthenticated) user context yet.
  • If you are rendering pages as PDF in your application use Visualforce. Lightning components don’t support rendering as PDF output yet.
  • If you are adding to an existing project with lots of Visualforce Pages continue to use Visualforce. Consider moving to Lightning components using Lightning components for Visualforce.

Now you are able to decide which tool to use. But, because web applications are taking more advantage of the app-centric model, I will encourage all Salesforce developers to learn at least the basics of Lightning components. You’ll want to use these components in your future development work.

Oauth Salesforce with Lightning Out

Posted on

Hi All,

In this article, I will explain the code which can be used for connecting and getting the records
from different or multiple salesforce organization using Apex and Lightning Out.

To start first you need to authorize URLs which can be accessed from salesforce environment.
Go to Setup > Administration Setup > Security Controls > Remote Site Settings.

Create one CONNECTED APP go to SETUP > BUILD > CREATE > APP > CONNECTED APP > NEW.

Create Custom Setting for Version,Client Id,Client Secret. Go to SETUP > BUILD > DEVELOP > CUSTOM Settings.

After completing all the steps let’s start coding.

CallBackURLController.apxc :

public with sharing class CallBackURLController{

    @AuraEnabled
    public Static List<Contact> getContacts(String Accesscode){
    
        version__c vrsn = [select name, ClientId__c, ClientSecret__c from version__c limit 1];
        Accesscode = Accesscode.replace('=','%3D').trim();
        String redireUri = 'https://skdomain-dev-ed--c.ap2.visual.force.com/apex/callbackurl';
        String loginUri = 'https://login.salesforce.com';
        String header = '';
        String endpoint = '';
                
        String reqbody = 'grant_type=authorization_code' + '&client_id=' + vrsn.ClientId__c +
            '&client_secret=' + vrsn.ClientSecret__c + '&code=' + Accesscode + '&redirect_uri=' + redireUri;
        
        endpoint = loginUri + '/services/oauth2/token?' + reqbody;
        
        Map<String, object> mapReqBody = CallBackURLController.getHTTPResponse(endpoint, header, 'POST');
        
        header = string.valueOf(mapReqBody.get('token_type')) + ' ' + string.valueOf(mapReqBody.get('access_token'));
        endpoint = loginUri + '/services/oauth2/userinfo';
        
        ///// User Info       
        Map<String, object> mapReqInfoBody = CallBackURLController.getHTTPResponse(endpoint, header, 'POST');
        
        ///// Query Request
        Map<String, object> mapURI = (Map<String, object>) mapReqInfoBody.get('urls');
        
        string queryUri = string.valueOf(mapURI.get('query')).replace('{version}',vrsn.name);
        endpoint = queryUri + '?q=select+id,Name,Phone,Email+from+contact+where+phone+!=null+limit+1000';
       
        Map<String, object> mapReqQryBody = CallBackURLController.getHTTPResponse(endpoint, header, 'GET');
        string strCons = JSON.serialize(mapReqQryBody.get('records'));
        list<contact> lstCon = (list<contact>) JSON.deserialize(strCons, List<contact>.class);
        return lstCon;
    }
    
    public static Map<String, object> getHTTPResponse(String endpoint, String header, String method){
        HttpRequest req = new HttpRequest();  
        req.setMethod(method);
        req.setEndpoint(endpoint);
        if(header != ''){
            req.setHeader('Content-Type', 'application/json');
            req.setHeader('Authorization', header);
        }
        Http httpReq = new Http();  
        HTTPResponse res = httpReq.send(req);
        return (Map<String, object>)JSON.deserializeUntyped(res.getBody());
    }
    
}

This class is making a callout to other Salesforce Org and fetching Contacts of that Salesforce Org.

LightningOutApp.app :

<aura:application access="GLOBAL" extends="ltng:outApp">
    <aura:dependency resource="c:LightningOutCmp" />
</aura:application>

LightningOutCmp.cmp :

<aura:component controller="CallBackURLController" implements="force:appHostable">
    <aura:attribute name="code" type="String" default=""/>
    <aura:attribute name="contacts" type="Contact[]" />
    <aura:if isTrue="{!v.code==''}">
    	<ui:button label="login into Other Org" press="{!c.redirect}"/>
        <aura:set attribute="else">
        	<ui:button label="Get Contacts" press="{!c.getCons}"/>
        </aura:set>
  	</aura:if> 
    
    <div id="tblDiv" style="display:none">
        <table>
            <tr>
                <th>Name</th>
                <th>Phone</th>
                <th>Email</th>
            </tr>
            <aura:iteration items="{!v.contacts}" var="con">
               <tr>
                   <td>{!con.Name}</td>
                   <td>{!con.Phone}</td>
                   <td>{!con.Email}</td>
                </tr>
            </aura:iteration>        
        </table>
    </div>
</aura:component>

This component will be used in Visualforce Page.

LightningOutCmpController.js :

({
	redirect : function(component, event, helper) {
        window.location.href = 'https://login.salesforce.com/services/oauth2/authorize?response_type=code&client_id=[YOUR CLIENT ID]&redirect_uri=[REDIRECT URL]&prompt=login&display=popup';        
    },
    getCons : function(component, event, helper) {
        document.getElementById("tblDiv").style.display = "block";
        var code = component.get("v.code");        
    	helper.getContacts(component, code);
    },
}

Redirect() function will redirct to the login page for Salesforce Login. getCons() function will get Contact from logged in Salesforce Org.

LightningOutCmpHelper.js :

({
    getContacts: function(component, code) {        
        var action = component.get("c.getContacts");
        action.setParams({
            "Accesscode": code
        });
        var self = this;
        action.setCallback(this, function(actionResult) {
            component.set("v.contacts", actionResult.getReturnValue());       
        });        
        $A.enqueueAction(action);
    },
})

CallBackUrlPage.page

<apex:page showHeader="false" sidebar="false" standardStylesheets="false">
 <!-- Lightning Resources-->
    <apex:includeScript value="/lightning/lightning.out.js" /> 
    <!-- JavaScript to make Remote Objects calls -->
    <script>
        var code="{!$CurrentPage.parameters.code}";
        
        $Lightning.use("c:LightningOutApp", function() {
            $Lightning.createComponent("c:LightningOutCmp",
                  { "code" : code },
                  "lightningComponent",
                  function(cmp) {
                    // any further setup goes here
            });
        });
    </script>
     
    <!-- Lightning Component -->
    <div id="lightningComponent"/>
</apex:page>

When completed it will look like this.

12204800_921217127916108_1436226568_n 12204574_921217134582774_409109935_n 12207968_921217131249441_1515473630_n 12208016_921217124582775_1057121612_n

 

When you click on “Login into Other Org” it will prompt you to login to salesforce. After logging in it will redirect you to Component Page and when you click on “Get Contacts” button it will fetch records from other Salesforce Org.

 

Why use Lightning? and not other JS Frameworks

Posted on Updated on

Salesforce introduced Salesforce1 Lightning Components last year(2014) at Dreamforce. Lightning components give you a client-server framework based up JavaScript that is native to the Salesforce1 platform. It comes complete with an event-driven architecture that is optimized for fast Single Page Apps. If you are familiar with frameworks like AngularJS, Backbone and React you will know how Salesforce1 Lightning Framework is better from these frameworks.

build-nextgen-apps-faster-with-lightning-components-7-638

AngularJS : 

It was first released in 2009 and made available as open source framework under MIT license. Ever since its release, Angular ecosystem has grown beyond imagination. It currently boasts the biggest community of developers and is the most used JavaScript framework for developing Single Page Web Applications. AngularJS framework gives super powers to HTML by adding all the necessary features required to build dynamic views (interactive user interface). It gives option to extend HTML attributes by the use of Angular directives. Extending HTML with AngularJS is very simple, one can use standard AngularJS directive or develop a custom directive and use it on any div. Two way data binding is at the core of Angular.js.

BackboneJS :

It was first released in 2010 by Jeremy Ashkenas as open source JavaScript Framework under MIT license. It is a lightweight JavaScript Framework, it is simple, small size package and easy to learn. You can get started building apps with Backbone JavaScript Framework within no time. It is growing slow even though biggies like Pinterest, Foursquare, Walmart, Disqus are using backone.js. The main reason for that appears to be the sluggish release cycle of backbone and lack of power features that other frameworks offer out of the box. It is useful but more as a side framework rather than the core framework of your web project.

React :

ReactJS was first released as open source in 2013 under BSD license.React.js JavaScript Framework is behind the user interface of Facebook as well as Instagram. This gives us a quick idea about how powerful is ReactJS when it comes to building large scale applications of extreme dynamic nature. The community is growing rapidly ever since its release and it is the fastest growing JavaScript framework as of today. One can find tons of resources, tutorials and React component libraries to get going within no time. ReactJS is best at rendering complex user interfaces with high performance. The basic fundamental behind React is the concept of virtual DOM. ReactJS utilizes a virtual DOM, which can be rendered either at client side or server side and communicate back and forth. When the data manipulation is much more dynamic and complex, client side DOM manipulations become performance intensive.

Lightning Components : 

Lightning is different from above frameworks it is designed first and foremost for enterprise applications. Lighting has a rich event driven architecture that appeals to JavaScript developers and all of the power of the Force.com platform. The power of the component framework is in its ease of customization. Developers can combine multiple components into larger ones or even applications.

Lighting components encapsulate functionality, markup and CSS into reusable functional units that can be assembled into larger components or complete application. Using appHostable tag you can expose your component in Salesforce1 and it will become a mobile application.

Like other component frameworks where you typically have to roll your own backend functionality, authentication and connectivity, with Lightning you simply expose server-side Apex functionality with a single annotation and then instruct the component to utilize it.And now you have access to workflow, data validation, queues, bulk processing, reporting, dashboards much more.

Below are the features which tell you, why use Lightning and not other JS Framework?

  1. Lightning is NATIVE to Salesforce.
  2. INTEGRATED with Salesforce1.
  3. Commercial AppExchange
  4. Support OTHER JavaScript frameworks.
  5. METADATA
  6. EXTENDABLE and Resuable across apps and orgs.
  7. Encapsulated markup, logic and style.
  8. Responsive UI
  9. Loose coupling with a publish/subscribe eventing model.

Will Lightning applications and components replace other JS Frameworks? May be but time will tell. Should you get started building Lightning components now? Absolutely Yes!!!  🙂

 

Referencing Apex Map in Lightning Component

Posted on Updated on

Hi All,

In this post will show you, how to reference Apex Map in Lightning Components?
In visualforce, you can directly process map using markup. But in Lightning Component you can’t process map using Lightning Markup.

Here is the complete code.Let’s walk through code

MapDemoController.apxc :

public class MapDemoController{
    
    @AuraEnabled
    public static Map<Id,Contact> getContacts(){
        Map<Id,Contact> conMap = new Map<Id,Contact>([SELECT Id,FirstName,LastName,Phone,Email FROM Contact LIMIT 100]);
        
        return conMap;
    }
}

getContacts() method is passing a Map of contact to Lightning Component.

MapDemoComp.cmp :

<aura:component controller="MapDemoController">
	<ltng:require styles="/resource/SLDS/assets/styles/salesforce-lightning-design-system-vf.css"/>
	<!-- Attribute Definition -->
    <aura:attribute name="contacts" type="Map" />
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
    
    <div class="slds">
        <div id="contactDetail"></div>
    </div>
    
</aura:component>

aura:attribute type is defining type to Apex Map. Defining this map in this component is of no use as I am not using this map in the component directly.
But if you are passing map from some other component/app, this can be used to assign map.

MapDemoCompController.js :

({
	doInit : function(component, event, helper) {
		var action = component.get("c.getContacts");//Fetching Map from Controller
        action.setCallback(this, function(a) {
            component.set("v.contacts", a.getReturnValue());//Set return value to Contact Map
            var contacts = component.get("v.contacts");//Getting Map and Its value
            
			var tile='<ul class="slds-list--vertical slds-has-cards">';
			
            for (key in contacts){
                tile += '<li class="slds-list__item">';
                tile += '<div class="slds-tile slds-tile--board">';
                tile += '<div class="slds-tile__detail">';
                tile += '<p class="slds-text-heading--medium">'+ contacts[key].FirstName+' '+ contacts[key].LastName +'</p>';
                tile += '<p class="slds-truncate">Email - '+ contacts[key].Email +'</p>';
                tile += '<p class="slds-truncate">Phone - '+ contacts[key].Phone +'</p>';
                tile += '</div>';
                tile += '</div>';
                tile += '</li>';
            }
            tile += '</ul>';
            document.getElementById("contactDetail").innerHTML = tile;            
        });
        $A.enqueueAction(action);
	}
})

component.set(“v.contacts”, a.getReturnValue()) is used to set “v.contacts” map.
component.get(“v.contacts”) is used to get “v.contacts” map.
I could directly assign returned value from a.getReturnValue() to javascript variable. But to show you how you can set or get map, I did in this way.
contacts[key].FieldName is used to retrieve value from map.

🙂

Lightning Component, Remote Objects and Visualforce Page

Posted on

Hi All,

In my last post I showed JavaScript Remoting with Lightning Component. In this post I will show you other feature of VisualForce with Lighting Component which is Remote Objects. The Visual Remote Objects supports basic DML operation like create read, update and delete in JavaScript without writing even a single line of Apex code.

You can read more about Remote Objects here at Harshit Pandey’s Blog.

Let’s walk through code

JSRemoteComp.cmp :

<aura:component>
    
    <ltng:require scripts="/resource/stockfiles/stockfiles/jquerymin.js" 
                  afterScriptsLoaded="{!c.myAction}"/>
    
	<aura:attribute name="accounts" type="Account[]"></aura:attribute>
    
    <!-- REQUIRED SLDS WRAPPER -->
    <div class="slds">
        <!-- Page Header -->
        <div class="slds-page-header">
            <div class="slds-grid">
                <div class="slds-col slds-has-flexi-truncate">
                    <h1 class="slds-text-heading--medium slds-truncate" title="Account Information">Account Information</h1>
                </div>
            </div>
        </div>
        <!-- TABLE - BADGE COMPONENT -->
        <table id="tb" class="slds-table slds-table--bordered">
            <thead>
                <tr class="slds-text-heading--label">
                    <th scope="col">
                        <span class="slds-truncate">Name</span>
                    </th>
                    <th scope="col">
                        <span class="slds-truncate">Phone</span>
                    </th>
                    <th scope="col">
                        <span class="slds-truncate">Active</span>
                    </th>
                </tr>
            </thead>
        </table><!-- TABLE - BADGE COMPONENT -->
    </div><!-- REQUIRED SLDS WRAPPER -->  
</aura:component>

This Lighting Component will output Accounts passed from VisualForce Page.

JSRemoteCompController.js :

({
	myAction : function(component, event, helper) {
		var accounts = component.get("v.accounts");
        var row = '<tbody>';
        accounts.forEach(function(account) {
            row += '<tr class="slds-hint-parent">';
            row += '<td data-label="activity">';
            row += '<span class="slds-truncate">'+account.get("Name")+'</span></td>';
            row += '<td data-label="confidence">';
            row += '<span class="slds-truncate">'+account.get("Phone")+'</span></td>';
            row += '<td data-label="confidence">';
            row += '<span class="slds-truncate">'+account.get("Active__c")+'</span></td>';
            row += '</tr>';
        });
        row += '</tbody>';
        jQuery('#tb').append(row);
        
	}
})

In order to display a Lightning Component in a Visualforce page, you need to construct a simple Lightning Application that is used as the bridge between the two technologies. This needs to have a dependency on the Lightning Component that will display the content, I used JSRemote in this case.

JSRemote.app :

<aura:application access="GLOBAL" extends="ltng:outApp">
    <aura:dependency resource="c:JSRemoteComp" />
</aura:application>

Once the app is in place, there is markup in the Visualforce page to tie things together – note that the Lightning Component is constructed dynamically via JavaScript, rather than being included in the page markup server side.

JSRemoteDemo.page :

<apex:page standardStylesheets="false" sidebar="false" showHeader="false">
    
    <!-- Lightning Resources-->
    <apex:includeScript value="/lightning/lightning.out.js" />
    <apex:stylesheet value="/resource/SLDS/assets/styles/salesforce-lightning-design-system-vf.css"/>
    
    <!-- Remote Objects definition to set accessible sObjects and fields -->
    <apex:remoteObjects >
        <apex:remoteObjectModel name="Account" jsShorthand="Warehouse" fields="Id,Name,Active__c,Phone"></apex:remoteObjectModel>
    </apex:remoteObjects>

    <!-- JavaScript to make Remote Objects calls -->
    <script>
        fetchWarehouses();
        function fetchWarehouses(){
            // Create a new Remote Object
            var wh = new SObjectModel.Warehouse();
            
            // Use the Remote Object to query for 10 warehouse records
            wh.retrieve({ limit: 100 }, function(err, records, event){
                if(err) {
                    alert(err.message);
                }
                else {
                    //Adding Lightning Component Here
                    $Lightning.use("c:JSRemote", function() {
                        $Lightning.createComponent("c:JSRemoteComp",
                              { "accounts" : records },
                              "lightningComponent",
                              function(cmp) {
                                // any further setup goes here
                        });
                    });
                }
            });
        }
    </script>
    
    <!-- Lightning Component -->
    <div id="lightningComponent"/>
    
    
</apex:page>

Output will look similar to this.

remoteobj

So That’s It.

Lightning Component, JavaScript Remoting and Visualforce Page

Posted on Updated on

Hi All,

New Winter 16 feature allows Lighting Components to be embedded inside a Visualforce Page.We know Lightning Components are used as building blocks for faster development of mobile and web app. I thought to embed Lightning Component with some of the features of VisualForce Page which are optimized for use on mobile pages and on pages that use third-party JavaScript libraries. It enables dynamic, interactive pages that feel more responsive than traditional Visualforce pages. JavaScript Remoting is one the features which can be used to make mobile pages. This feature of Visualforce can be combine with Lighting Components to make more interactive pages that feel more responsive than traditional Visualforce pages. You can read more about JavaScript Remoting here.

Let’s walk through code

AccountRemoter.apxc :

global with sharing class AccountRemoter {

    public String accountName { get; set; }
    public static List<Account> accountList{ get; set; }
    
    //Remote Function
    @RemoteAction
    global static List<Account> getAccount(String accountName) {
    
        string tempName = '\'%' + accountName + '%\' ';
        String query = 'SELECT Id, Name, Phone, Active__c FROM Account WHERE Name like' + tempName;
        accountList = Database.Query(query);
        
        return accountList;
    }
}

In this class I have created a RemoteAction method which will return list of accounts. @RemoteAtion annotation is used to define a remote action method.

JSRemoteComp.cmp :

<aura:component>
    <!-- Attribute -->
	<aura:attribute name="accounts" type="Account[]"/>
    <!-- REQUIRED SLDS WRAPPER -->
    <div class="slds">
        <!-- Page Header -->
        <div class="slds-page-header">
            <div class="slds-grid">
                <div class="slds-col slds-has-flexi-truncate">
                    <h1 class="slds-text-heading--medium slds-truncate" title="Account Information">Account Information</h1>
                </div>
            </div>
        </div>
        <!-- TABLE - BADGE COMPONENT -->
        <table class="slds-table slds-table--bordered">
            <thead>
                <tr class="slds-text-heading--label">
                    <th scope="col">
                        <span class="slds-truncate">Name</span>
                    </th>
                    <th scope="col">
                        <span class="slds-truncate">Phone</span>
                    </th>
                    <th scope="col">
                        <span class="slds-truncate">Active</span>
                    </th>
                </tr>
            </thead>
            <tbody>
                <aura:iteration items="{!v.accounts}" var="account">
                    <tr class="slds-hint-parent">
                        <td data-label="activity">
                            <span class="slds-truncate">{!account.Name}</span>
                        </td>
                        <td data-label="confidence">
                            <span class="slds-truncate">{!account.Phone}</span>
                        </td>
                        <td data-label="confidence">
                            <span class="slds-truncate">{!account.Active__c}</span>
                        </td>
                    </tr>
                </aura:iteration>
            </tbody>
        </table><!-- TABLE - BADGE COMPONENT -->
    </div><!-- REQUIRED SLDS WRAPPER -->
</aura:component>

This Lighting Component will output Accounts searched from VisualForce Page.

In order to display a Lightning Component in a Visualforce page, you need to construct a simple Lightning Application that is used as the bridge between the two technologies. This needs to have a dependency on the Lightning Component that will display the content, I used JSRemote in this case.

JSRemote.app :

<aura:application access="GLOBAL" extends="ltng:outApp">
    <aura:dependency resource="c:JSRemoteComp" />
</aura:application>

Once the app is in place, there is markup in the Visualforce page to tie things together – note that the Lightning Component is constructed dynamically via JavaScript, rather than being included in the page markup server side.

JSRemoteDemo.page :

<apex:page controller="AccountRemoter" standardStylesheets="false" sidebar="false" showHeader="false" >
    
    <!-- Lightning Resources-->
    <apex:includeScript value="/lightning/lightning.out.js" />
    <apex:stylesheet value="/resource/SLDS/assets/styles/salesforce-lightning-design-system-vf.css"/>
    
    <script type="text/javascript">
        function getRemoteAccount() {
            var accountName = document.getElementById('acctSearch').value;
            document.getElementById("lightningComponent").innerHTML = " ";
            document.getElementById("responseErrors").style.display = "none";
            
            //Remote Function
            Visualforce.remoting.Manager.invokeAction(
                '{!$RemoteAction.AccountRemoter.getAccount}',
                accountName, 
                function(result, event){
                    if (event.status) {
                        
                        if(result.length > 0){
                            //Adding Lightning Component Here
                            $Lightning.use("c:JSRemote", function() {
                                $Lightning.createComponent("c:JSRemoteComp",
                                      { "accounts" : result },
                                      "lightningComponent",
                                      function(cmp) {
                                        // any further setup goes here
                                });
                            });
                            
                        }else{
                            document.getElementById("responseErrors").style.display = "block";
                            document.getElementById("responseErrors").innerHTML = "No Records Found";
                        }
                        
                    } else if (event.type === 'exception') {
                        document.getElementById("responseErrors").style.display = "block";
                        document.getElementById("responseErrors").innerHTML = 
                            event.message + "
\n




<pre>" + event.where + "</pre>

";
                    } else {
                        document.getElementById("responseErrors").style.display = "block";
                        document.getElementById("responseErrors").innerHTML = event.message;
                    }
                },
                {escape: true}
            );
        }
    </script>
<div class="slds">
        <input id="acctSearch" class="slds-input" type="text" placeholder="Search Account"/>
        <button class="slds-button slds-button--neutral" onclick="getRemoteAccount()">Get Account</button>
        <!-- Error Message -->
<div id="responseErrors" style="display:none;" class="slds-notify slds-notify--alert slds-theme--error slds-theme--alert-texture" role="alert">
        </div>
</div>

    <!-- Lightning Component -->
<div id="lightningComponent"/>
</apex:page>

Output will look similar to this.

jsremoting

So That’s It.

Show Contacts on Google Map

Posted on Updated on

Hi All,

In this article I will tell you how you can show your Contacts with their Locations on Google Map.In this example I am using Social Profile pictures of Contacts to show on Map.If you want to see your Profile picture you have to login from any of your social profile.If you do not want to use Contact’s social profile, you can modify code to use Attachments related to these Contacts.

Screenshot_2015-10-13-10-39-49

Let’s walk through the code.

ContactsOnGoogleMapController Class :

public class ContactsOnGoogleMapController{
    
    public String contactJson{get;set;}
    
    public ContactsOnGoogleMapController(){
        
        List<Contact> conList = [select Id,Name,Email,Phone,MailingLatitude,MailingLongitude,MailingStreet,MailingCity,MailingState,MailingCountry,PhotoUrl from Contact Order By CreatedDate DESC LIMIT 5];
        
        String baseURL = 'https://ap2.salesforce.com';
        String coma = '';
        
        if(conList.size() > 0){
            contactJson = '[';
            
            for(Contact con : conList){
                contactJson += coma + '{\"title\":\"' + con.Name + '\",'+
                                '\"lat\": \"' + con.MailingLatitude + '\",'+
                                '\"lng": \"' + con.MailingLongitude +'\",'+
                                '\"address\": \"' + con.MailingStreet +' '+ con.MailingCity +'<br/>'+ con.MailingState + '<br/>' +con.MailingCountry + '\",'+
                                '\"contact\": \"' + con.Phone + '\",'+
                                '\"icon\": \"' + baseURL +''+ con.PhotoUrl + '\"}';
                                
                coma = ',';
            }
            
            contactJson += ']';
            
        }
    }
    
}

In this controller I am querying Contact’s records.From Contact List I am creating a JSON string to pass on VF Page.

ContactsOnGoogleMap VF Page :

<apex:page controller="ContactsOnGoogleMapController" showHeader="false" sidebar="false" standardStylesheets="false">

    <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
    
    <script type="text/javascript">
        var mapicon = JSON.parse('{!contactJson}');
        
        window.onload = function () {
            LoadMap();
        }
        function LoadMap() {
            var mapOptions = {
                center: new google.maps.LatLng(mapicon[0].lat, mapicon[0].lng),
                zoom: 8,
                mapTypeId: google.maps.MapTypeId.ROADMAP
            };
            var infoWindow = new google.maps.InfoWindow();
            var latlngbounds = new google.maps.LatLngBounds();
            var map = new google.maps.Map(document.getElementById("dvMap"), mapOptions);
            
            for (var i = 0; i < mapicon.length; i++) {
                var data = mapicon[i]
                var myLatlng = new google.maps.LatLng(data.lat, data.lng);
                
                var image = {
                    url: data.icon,
                    size: new google.maps.Size(100, 65),
                    origin: new google.maps.Point(0, 0),
                    anchor: new google.maps.Point(17, 34),
                    scaledSize: new google.maps.Size(65, 65)
                };
                
                var marker = new google.maps.Marker({
                    position: myLatlng,
                    map: map,
                    title: data.title,
                    icon: image,
                    contact: data.contact
                });
                
                (function (marker, data) {
                    google.maps.event.addListener(marker, "click", function (e) {
                        infoWindow.setContent("<div style = 'width:100%;height:40%'><img width='60px' height='60px' align = 'middle' src = '" + data.icon + "' />&nbsp;&nbsp;<b>"+ data.title + "<b/><br/><a href=tel:["+data.contact+"]>"+data.contact+"<img style='vertical-align:top' width='20' height='18' src='/resource/dial'/></a><br/>"+data.address+"</div>");
                        infoWindow.open(map, marker);
                    });
                })(marker, data);
                latlngbounds.extend(marker.position);
         
            }
            
            var bounds = new google.maps.LatLngBounds();
            map.setCenter(latlngbounds.getCenter());
            map.fitBounds(latlngbounds);
        }
        
    </script>
    
    <div id="dvMap" style="width: 100%; height: 600px">
    </div>
    
</apex:page>

Above script is used to show Contacts with their information.

So That’s It.

Lightning Design System with Lightning Component

Posted on Updated on

Hi All,

Salesforce just made a major announcement ahead of Dreamforce by introducing Lightning Design System.With the Design System you can build custom applications with a look and feel that is consistent with Salesforce core features — without reverse engineering your styles.

After browsing the docs I decided to have a try with a SLDS.In this article I am just telling a basic example of SLDS and how you can use it with Lightning Component? If you haven’t looked at the SLDS yet, the best place to start is by getting your Trailhead badge for the Lightning Design System module.

I just updated my previous post with SLDS you can find the orignal post here, you can use Apex class from this post.

img1

Application :

<aura:application controller="bklightning.WClassController">
	<!-- REQUIRED SLDS CSS -->
	<ltng:require styles="/resource/SLDS080/assets/styles/salesforce-lightning-design-system-vf.css"/>
	
	<aura:attribute name="accounts" type="bklightning.WrapperClass"/>
	<aura:handler name="init" value="{!this}" action="{!c.doInit}" />
	
	<!-- REQUIRED SLDS WRAPPER -->
	<div class="slds">
		<!-- Page Header -->
		<div class="slds-page-header">
			<div class="slds-grid">
				<div class="slds-col slds-has-flexi-truncate">
				  <h1 class="slds-text-heading--medium slds-truncate" title="Account Information">Account Information</h1>
				</div>
			</div>
		</div>
		<!-- TABLE - BADGE COMPONENT -->
		<table class="slds-table slds-table--bordered">
		  <thead>
			<tr class="slds-text-heading--label">
			  <th scope="col">
				<span class="slds-truncate">Name</span>
			  </th>
			  <th scope="col">
				<span class="slds-truncate">Contact</span>
			  </th>
			  <th scope="col">
				<span class="slds-truncate">Active</span>
			  </th>
			</tr>
		  </thead>
		  <tbody>
			<aura:iteration items="{!v.accounts}" var="account">
				<tr class="slds-hint-parent">
				  <td data-label="activity">
					<span class="slds-truncate">{!account.acc.Name}</span>
				  </td>
				  <td data-label="stage">
					<span class="slds-truncate">{!account.count}</span>
				  </td>
				  <td data-label="confidence">
					<span class="slds-truncate">{!account.acc.bklightning__Active__c}</span>
				  </td>
				</tr>
			</aura:iteration>
		  </tbody>
		</table><!-- TABLE - BADGE COMPONENT -->
		
	</div><!-- REQUIRED SLDS WRAPPER -->
	
</aura:application>

The markup is wrapped in a div with the class ‘slds’ as the LDS is namespaced – so any styles that I use need to be inside an ancestor with this class or they will revert back to very ordinary looking HTML.Lightning Design System works like Bootstrap.The only draw back of LDS is it only provides you CSS(Designs) not functionality.Means if you want to fire an event onclick of button you have to write JAVACRIPT/JQUERY/CSS or use external jquery/css.

So That’s It.

Export Data in any format

Posted on Updated on

Hi All,

In this article i will be telling you how to export table data in any format like Excel, CSV, JSON, PDF, PNG.To implement this functionality I am using jQuery Library.

Credit : here.

pic

Plugin Features :

We can easily export any html tables to the following formats

  1. JSON
  2. XML
  3. PNG
  4. CSV
  5. TXT
  6. MS-Word
  7. Ms-Excel
  8. PDF

Script :

    $(document).ready(function(){
         $(".toggle").on("click",function(){
              var elm = $("#"+$(this).data("toggle"));
              if(elm.is(":visible"))
                  elm.addClass("hidden").removeClass("show");
              else
                  elm.addClass("show").removeClass("hidden");
              return false;
         });
    });

Button Panel :

<div class="pull-right">
	<button class="btn toggle" data-toggle="exportTable"><i class="fa fa-bars"></i> Export Data</button>
</div>
<div class="panel-body" id="exportTable" style="display:none">
	<div class="row">
		<div class="col-md-3">
			<div class="list-group border-bottom">
				<a href="#" class="list-group-item" onClick ="$('#contacts').tableExport({type:'json',escape:'false'});"><img src="{!URLFOR($Resource.tableExporter,'tableExporter/images/json.png')}" width="24"/> JSON</a>
				<a href="#" class="list-group-item" onClick ="$('#contacts').tableExport({type:'json',escape:'false',ignoreColumn:'[2,3]'});"><img src="{!URLFOR($Resource.tableExporter,'tableExporter/images/json.png')}" width="24"/> JSON (ignoreColumn)</a>
				<a href="#" class="list-group-item" onClick ="$('#contacts').tableExport({type:'json',escape:'true'});"><img src="{!URLFOR($Resource.tableExporter,'tableExporter/images/json.png')}" width="24"/> JSON (with Escape)</a>
			</div>
		</div>
		<div class="col-md-3">
			<div class="list-group border-bottom">
				<a href="#" class="list-group-item" onClick ="$('#contacts').tableExport({type:'xml',escape:'false'});"><img src="{!URLFOR($Resource.tableExporter,'tableExporter/images/xml.png')}" width="24"/> XML</a>
				<a href="#" class="list-group-item" onClick ="$('#contacts').tableExport({type:'txt',escape:'false'});"><img src="{!URLFOR($Resource.tableExporter,'tableExporter/images/txt.png')}" width="24"/> TXT</a>
			</div>
		</div>
		<div class="col-md-3">
			<div class="list-group border-bottom">
				<a href="#" class="list-group-item" onClick ="$('#contacts').tableExport({type:'csv',escape:'false'});"><img src="{!URLFOR($Resource.tableExporter,'tableExporter/images/csv.png')}" width="24"/> CSV</a>
				<a href="#" class="list-group-item" onClick ="$('#contacts').tableExport({type:'excel',escape:'false'});"><img src="{!URLFOR($Resource.tableExporter,'tableExporter/images/xls.png')}" width="24"/> XLS</a>
				<a href="#" class="list-group-item" onClick ="$('#contacts').tableExport({type:'doc',escape:'false'});"><img src="{!URLFOR($Resource.tableExporter,'tableExporter/images/word.png')}" width="24"/> Word</a>
			</div>
		</div>
		<div class="col-md-3">
			<div class="list-group border-bottom">
				<a href="#" class="list-group-item" onClick ="$('#contacts').tableExport({type:'png',escape:'false'});"><img src="{!URLFOR($Resource.tableExporter,'tableExporter/images/png.png')}" width="24"/> PNG</a>
				<a href="#" class="list-group-item" onClick ="$('#contacts').tableExport({type:'pdf',escape:'false'});"><img src="{!URLFOR($Resource.tableExporter,'tableExporter/images/pdf.png')}" width="24"/> PDF</a>
			</div>
		</div>
	</div>
</div>

Records Table :

<div class="panel panel-default">
	<div class="panel-heading">
		<h3 class="panel-title">Contact Details</h3>
	</div>
	<div class="panel-body panel-body-table">
		<table id="contacts" class="table table-striped">
			<thead>
				<tr>
					<th>FirstName</th>
					<th>LastName</th>
					<th>Email</th>
					<th>Phone</th>
				</tr>
			</thead>
			<tbody>
			<apex:repeat value="{!contacts}" var="con">
				<tr>
					<td>{!con.FirstName}</td>
					<td>{!con.LastName}</td>
					<td>{!con.Email}</td>
					<td>{!con.Phone}</td>
				</tr>
			</apex:repeat>
			</tbody>
		</table>
	</div>
</div>

So That’s It.