When Salesforce is life!

Tag: Lightning Page 1 of 2

[Salesforce / Lightning] Simple Custom Modal Alert

Hello everybody!

This is an “easy peasy” post that comes from a recent two-weeks full immersion on Lightning Components task I got into at work: there will be more content from this activity and a Cagliari DG presentation as well.

For all the TL;DR guys (and again, I’m one of you!), here is the Github Repository.

The Alert Modal shows an alert modal through a custom event fired from your Lightning components:

var evt = $A.get("e.c:AlertEvt");
        evt.setParams({
            "show": true,                     //shos alert
            "mode": 'prompt',                 //alert mode: prompt, alert, toast
            "fixed": false,                   //fixed does not shows any "close" button
            "type": 'info',                   //type of alert: info, success, warning, error
            "message": 'Title Message',       //main title
            "details": 'Message Details. . .' //details message
        });
        evt.fire();

The event is caught up by the AlertCmp Lightning component that shows the request alert:

Besides the prompt mode, you can use the alert mode:

And a toast mode:

You can test the component in the provided Lightning app:

[Salesforce / Lightning] Of the #Lightning afraid be not!

I was introduced to the Lightning world at its very beginning by Jeff Douglas when I was an active member of the Top Coder community.

At that time there were soo few standard components, no way to add a Lightning app / component in a Visualforce Page or easily integrate Lightning with your existing CRM.

Plus it was so hard to make it work, no documentation, no examples, no debugging, but you could feel the beginning of something that would have innovated the platform.

In months the set of components exploded, the posts about Lightning become more and more common, people started sharing their discoveries, trailhead modules were added and the Lightning Design System allowed developers to give their apps the right look and feel.

So what do you need to finally become an expert of this awesome technology?

If you are completely unaware of what Lightning is, start with the Lightning Tralihead Modules:

Once you have a good overview on the technology I suggest to fall into the official lightning guide (always up to date): here you will find everything about the framework.

This is were I first learnt all, well written, easy to understand, covers the whole framework…and it’s free!

Have also a look to the Lightning Design System official site: I suggest you to use this library to make your components as much “Salesforcish” as possibile for a perfect UI experience.

Feeling an expert now?

The next step is to develop something unique and amazing with your new set of skills.

I’ve written in the past years a couple of custom Lightning components (browse here), and this is the good way to master the technology: pick a use case (it can be even a simple component like a progress bar or a related list component) and try to port it in Lightning using the Lightning Design System.

At first you’ll feel a bit uncomfortable but as long as you keep coding you’ll get more and more confidence with the framework and learn more and more tricks, understanding a new way of developing in your CRM.

Don’t be afraid, you’ll never get bored of it, I’ll just get in love with it and appreciate a new and different way to think code.

If you’ve never developed in Javascript you can be a bit puzzled at the beginning, but I guarantee this new way of developing in the platform will increase your programming skills to a new level.

This does not mean you’ll forget all about Visualforce, some customers still don’t use Lightning so the marriage Visualforce + Apex will continue for years, but even if you won’t have any chance to use Lightning with a customer’s project, there is no reason you should not start learning and mastering it!

Next step?

Open your Tralihead account and start learning Lightning, you won’t regret it ! (MVPs never lie!)

[Salesforce / Lightning] Geolocation Fun with Location Aware Lightning Components

Summer 16 platform release came up with Automatic Geocodes for Addresses: your Accounts, Contacts and Leads addresses are now automatically geocoded using Data.com.

This means that the Latitude, Longitude and Accuracy fields are automatically populated after an address is filled (more details here).

Let’s combine this awesome new feature with Lightning Components to create a component to show the nearest accounts (using the Billing Address) to the Company location.

TL;DR here is the Github repository.

To achieve this we have to make few configurations to enable the new feature.

At first activate the Data.com Clear Rules for the Account’s Billing Address:

This means that when a new Account is created and the the Billing Address is filled in, Data.com will try to geolocate the address and fill the BillingLongitude, BillingLatitude and BillingAccuracy fields.

We want to use the Company geolocation as the “center” of the geo-search; unfortunately Data.com cleans Accounts, Contacts and Leads address only.

We can update the Organization‘s Latitude, Longitude fields manually: unfortunately these fields are updatable via SOAP API only.

To do this grab a valid Salesforce session id. The easiest way is to grab it from an open Salesforce tab using your browser’s developer console:

You also need your ORG’s ID: you can pick it up from Setup > Company Information or by simply querying Select Id From Organization.

Open your favorite request maker app (e.g. Request Maker) and make the following SOAP call:

Method: POST
Endpoint: https://your_org_instance/services/Soap/c/37.0/
Headers:
    Content-Type: text/xml; charset=utf-8
    SOAPAction: update
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
 xmlns:urn="urn:enterprise.soap.sforce.com" 
 xmlns:urn1="urn:sobject.enterprise.soap.sforce.com"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <soapenv:Header>
      
      <urn:SessionHeader>
         <urn:sessionId>SESSION_ID</urn:sessionId>
      </urn:SessionHeader>
   </soapenv:Header>
   <soapenv:Body>
      <urn:update>
         <urn:sObjects xsi:type="urn1:Organization">
            <Id>ORG_ID</Id>
            <Longitude>9.114845271216465</Longitude>
            <Latitude>39.21264936045958</Latitude>
         </urn:sObjects>
      </urn:update>
   </soapenv:Body>
</soapenv:Envelope>

The component we are going to build is based on Creating a Salesforce Lightning Map Component By Christophe Coenraets.

The component will query for accounts whose location is inside a given radius in km/mi.

The first thing is to create an Apex Class capable of this query, the AccountsOnMapController, which includes the following query:

Organization orgDetails = [SELECT Id, Longitude, Latitude FROM Organization WHERE Id = :UserInfo.getOrganizationId()];
result.accounts = [Select Id, Name, BillingStreet, BillingCity, BillingCountry, BillingState, BillingPostalCode,
                BillingLatitude, BillingLongitude From Account Where BillingLatitude != null
    and DISTANCE(BillingAddress, GEOLOCATION(:orgDetails.Latitude, :orgDetails.Longitude), 'km') < :radius];

The component uses the Leaflet JS library as well and outputs the pins of all accounts found within the radius:

Each pin is clickable and in this simple implementation is capable of opening a new window with the given Account standard layout page:

The UI allow for radius and units modification, to query for different distances:

This component shows how easy is to play with location aware components, take it and add as many new features as you like!

[Salesforce / Lightning] #Cool Modal Dialog Component

Here we go with another simple UI component, made up with the new Lightning Design System.

Here you go a simple Modal dialog box.

For those of the TL;DR tribem here is the GitHub repository.

The component is ment to be placed in your app in this way:

<c:ModalDialog type="{!v.dialogType}" 
                   title="{!v.dialogTitle}" 
                   content="{!v.dialogContent}" 
                   showDialog="{!v.showDialog}"
                   context="{!v.dialogContext}"
                   inputValue="{!v.dialogInputValue}"
                   inputPlaceholder="{!v.dialogInputPlaceholder}"
                   onClose="{!c.dialogCallback}" />

And to be waken up by a boolean variable (in this case by v.showDialog).

When you switch this variabile to true/false the modal behaves as expected (shows up or closes).

This kind of architecture allow for a single callback after the modal closes, so you need a way to know what to do after this close event.

That is to say that you need to be aware of the context that triggered the modal.

The context parameter is a Javascript object that can contain wathever you want (I used an “action” string for instance, but you can put wathever variables you want) and is passed through to the onClose callback, here is an example:

{
    //ModalDialogTestAppController.js
    //. . .
    showAlert: function(component, event, helper) {
        $A.run(function(){
            helper.showDialog(component, 
                              'ALERT', //dialog type
                              'THIS IS AN ALERT!', //modal title
                              'Hello world!', //modal content
                              null, //input default string (only for "INPUT" type)
                              null, //input placeholder (only for "INPUT" type)
                              {
                                  action: helper.C.ACTIONS.SHOW_ALERT,
                                  anotherValue: Date.now(),
                              }, //context object
                              true); //show the dialog
        });
    },

The component supports the following parameters:

  • type:this is the type of dialog you want to open. Supports: ALERT, CONFIRM, INPUT, LOADER
  • title: title of the modal dialog
  • content: content text of the modal dialog
  • showDialog: boolean value that indicates if the modal is shown/hidden
  • context: Javascript object containing the context you want to be passed back to the callback invocation
  • inputValue: default value of the input field (only for INPUT type)
  • inputPlaceholder: placeholder for the input field (only for INPUT type)
  • onClose: callback called after the ModalDialogCloseEvt event is fired by the modal dialog component

The onClose callback is fired upon the ModalDialogCloseEvt event that supports the following parameters:

  • dialogType: the type of the calling dialog
  • confirmResult: true if the user pressed YES/OK buttons (always false for ALERT, LOADER)
  • inputResult: input written by the user (set only if type is INPUT and user pressed the OK button)
  • context: context sent to the component

These are the different kinds of dialogs:

ALERT

CONFIRM

INPUT

LOADER

And here it is the test app in action:

[Salesforce / Streaming API / On Demand] Streaming API Notification Lightning Component

UPDATE: With Winter ’15 you no longer can use a lightning context Session ID to make REST API calls, this component no longer works. Read Session Privilege Levels.

Few weeks ago I asked the community this simple question:

The Salesforce Community is awesome and suddenly I had cool answers.

I concentrated on the first one:

I didn’t want to simply explain how Streaming APIs work and at the same time I wanted to do something fun and while I was walking with my dog I thought:

If you have any idea please send me awesome and challenging on demand articles topics!

For TL;DR buddies, here is the complete GitHub repository.

First of all here is the complete guide on Salesforce Streaming APIs.

As usual, this is a “quick and dirty” blog post, so don’t expect me to explain how the magic works.

Streaming API is a cool set of APIs which allow a client to be notified from the server when a specific event occurs.

It works like push notifications and uses long polling, in the sense that the client polls for updates from the server but the server doesn’t answer back till the next event (the connection remains idle), and when the client receives finally the response it usually makes another logn polling request, and so on.

This is what happens:

  1. client connects to the server (handshake)
  2. client subscribes to a specific server event (called channel)
  3. client listens to that event using long polling
  4. server sends event
  5. client consumes the event
  6. back to step 2

This technology is based on the Bayeux protocol and supports the dialect of the CometD 2.0 library (that implements the Bayeaux protocol).

Here is some characteristics of the flow:

  • Maximum “client to server” post body size is 32,768 bytes (e.g. connect or subscribe methods)
  • After an event is received, the client has to reconnect withing 40 seconds or the server closes the connection and a new handshake is necessary
  • In case of network problems, the client should attempt an automatic reconnection and a new subscription
  • Client can subscribe to the meta/handshake channel to receive informations about the connection

Remember that “Streaming API doesn’t guarantee durability and reliable delivery of notifications“: the server does’nt keep any state so it doens’t keep track of what’s delivered.

Here is a simple guide of using Streaming API with Workbech.

Enable a PushTopic

The PushTopic SObject is the mean for creating a Streaming API channel.

It hosts the query that originates the events sent to the subscribers.

These are the PushTopics we are going to use in our project:

PushTopic pushTopic1 = new PushTopic();
pushTopic1.Name = 'Opportunity_Won';
pushTopic1.Query = 'SELECT Id, Amount, Name FROM Opportunity Where StageName='Closed Won'';
pushTopic1.ApiVersion = 36.0;
pushTopic1.NotifyForOperationCreate = true;
pushTopic1.NotifyForOperationUpdate = true;
pushTopic1.NotifyForFields = 'Where';
insert pushTopic1;

pushTopic = new PushTopic2();
pushTopic2.Name = 'Lead_Converted';
pushTopic2.Query = 'SELECT Id, Name,Company FROM Lead Where IsConverted = true';
pushTopic2.ApiVersion = 36.0;
pushTopic2.NotifyForOperationCreate = true;
pushTopic2.NotifyForOperationUpdate = true;
pushTopic2.NotifyForFields = 'Where';
insert pushTopic2;

The drivers of a PushTopic are:

  • Query: this is the query used to create the data pool
  • Operations: when a record has to scanned by the engine, that is on create, update, delete, udelete
  • Fields: the record is scanned when fields change if they are in the WHERE clause, SELECT clause, REFERENCE (where+select) or ALL (all fields changes trigger the PushTopic, if the where clause still apply)

In our examples we are subscribing to the create/update operations on the leads and opportunity when leads are converted and opportunities are closed and won.

Users will receive a notification if FLS (field level security) allow them to view the topic fields, if they have read access to the record and to the PushTopic, visibility on the record based on the sharing rules.

Limitations

The following objects can be used in the PushTopi query:

  • All Custom Objects
  • Account
  • Campaign
  • Case
  • Contact
  • Lead
  • Opportunity
  • Task (with few limitations)

And here you are a list of unsupported SOQL statements.

There are also a number of limits all exposed in this page.

The Lightning playroom

The GitHub repository provides the following components:

  • svg: replicates the svg HTML5 element not currently supported in Lightning components (outputs icons and stuff)
  • UINotification: used to display a alert/toast notification when a specific event occurs. You can choose the style (info, error, success, warning), type (Toast, Alert) and the timer in seconds for auto-hiding, and ofcourse a title and a content detail
  • StreamingAPIEvent: event fired when a specific channel sends an event
  • ShowNotificationEvent: event fired whan a Streaming API event is consumed and allow for displaying a notification
  • StrApiListener: subscribes client to one or several topics (only one component is allowed per app); it fires a StreamingAPIEvent event.
  • StrApiTopicTemplate: (global component) listens to the StreamingAPIEvent event, grabs its content, compile its templates for title and content and fires a ShowNotificationEvent to the unique notification center
  • StrApiNotificationDock: (global component) hosts the StrApiListener component and handles ShowNotificationEvent events, dynamically creating UINotification component

The StrApiTestApp hosts the following components instances:

<aura:application>
    <!-- ... -->

    <c:StrApiNotificationDeck topics="Opportunity_Won,Lead_Converted"
        apiVersion="36" 
        notificationType="Alert" />
    
    <c:StrApiTopicTemplate topic="Lead_Converted"
                                 style="warning" 
                                 title="Created new lead called {{Name}}"
                                 content="Company: {{Company}}"/>
    <c:StrApiTopicTemplate topic="Opportunity_Won"
                                 style="success" 
                                 title="Won $ {{Amount}} !"
                                 content="Name is {{Name}}" />
</aura:application>

The StrApiNotificationDeck subscribes to the Opportunity_Won and Lead_Converted PushTopics using an Alert notification style.

For each channel defines a StrApiTopicTemplate template with a proper notification style, title and content.

Title and Amount attributes can be templates referring to the corresponding SObject’s fields wrapped by the double moustaches ({{Field__c}}).

Run to https://xxx.lightning.force.com/c/StrApiTestApp.app:

Lightning App Builder

The StrApiNotificationDeck and StrApiTopicTemplate components are defined as global and implements the flexipage:availableForAllPageTypes interface so they are good to go with the Lightning App Builder.

Compoments are invisible so you are not expected to see anything on the builder: as far as I know there is not way to create a sort of “default” view for the builder.

And this is your Salesforce 1 brand new app:

Custom Streaming Channels

The Force.com platform allows for custom channels.

They can be access by:

  • Creating a new StreamingChannel object
  • Sending a notification to the channel using the Streaming Channel REST API

To create a new StreamingChannel go to All Tabs > Streaming Channel and create a new streaming channel:

The Name must include the “/u/” prefix. You can specify whichever path you like (e.g. /u/users/alerts, /u/sales/notifications).

The components we have creates supports this new kind of channel:

<c:StrApiNotificationDeck topics="Opportunity_Won,Lead_Converted,/u/CustomChannel"
        apiVersion="36" 
        notificationType="Alert" 
        hideAfter="5"/>
    
    <!-- . . . -->

    <!-- custom streaming channel -->
    
    <c:StrApiTopicTemplate topic="/u/CustomChannel"
                                 style="info" 
                                 title="Message received"
                                 content="{{$}}" />
    

The template component supports the {{$}} value that stands for “the whole data”.

Indeed the StreamingChannel supports only strings.

To execute a REST push call follow the following instructions, or manually execute the following call:

Header:

"method":"POST",
    "uri":"https://[YOUR_DOMAIN].salesforce.com/services/data/v36.0/sobjects/StreamingChannel/[STREAMING_CHANNEL_ID]/push",
    "headers":[
        {
            "key":"Authorization",
            "value":"Bearer [YOUR_SESSION_ID]"
        },
        {
            "key":"Content-Type",
            "value":"application/json"
        }
    ]

Body:

{ 
      "pushEvents": [
          { 
              "payload": "Broadcast message!!!!",
              "userIds": [] 
          },{ 
              "payload": "This message is only for Enreeco!!!",
              "userIds": ["00524000000eaVt"] 
          } 
       ] 
    }

The messages are composed by:

  • payload: the message to be sent (plain text)
  • userIds: leave empty Array for broadcast message, of add one or more user Ids

May the Force.com be with you!

[Salesforce / Lightning] Create your own Lightning Progress Bar

This is a repost from the article I wrote for the Salesforce Developer Blog.

Have you ever wanted a progress bar in your linghtning app?
I have and so I came up with a simple bootstrap library wrap up.

Following the successful Lightning series, I’m going to show you how I’ve made a simple Lightning Component out of the awesome Bootstrap library Bootstrap Progressbar (see details in the project’s home page).

For those who are in a TL;DR mode, here is the Github repository with the full code of the component and the demo app.

Let’s start with the component signature:

<c:ProgressBar 
 name="pb1" 
 valueMin="0"
 valueMax="1000"
 value="500"
 displayText="center"
 usePercentage="true"
 barContainerClass="progress-striped active" 
 barClass="progress-bar-info" 
 transitionDelay="10"
 displayText="center"/>

These are the attributes we can set:

  • name: name of the progress bar. This is used to ease events management
  • valueMin: bar minimum value, defaulted to 0
  • valueMax: bar maximum value, defaulted to 100
  • value: starting progress bar value
  • displayText: position of current value’s text (center or fill), blank for no text
  • usePercentage: shows the a % value text or value/max
  • barContainerClass: class of the container of the progress bar: this gives a style (leave blank for no additional effect, “progress-striped” for a “stripped” decoration and “active” to get a move)
  • barClass: this is to be applied to the bar, following the Bootstrap style (progress-bar-info, progress-bar-danger, progress-bar-warning, progress-bar-success, progress-bar-primary)
  • transitionDelay: delay in ms for the animation

This is an example of what you’ll see (simply use the provided app at https://YOUR_INSTANCE.lightning.force.com/c/ProgressBarApp.app):

The component uses 2 kind of events:

  • ProgressBarActionEvt: this is an event used to command the progress bar
  • ProgressBarMessageEvt: this is an event that is used by the progress bar to alert that the MIN/MAX values has been reached

ProgressBarActionEvt

<aura:event type="APPLICATION" description="Inbound event to guide the progress bar" >
    <aura:attribute name="value" type="Integer" default="" 
                    description="Value of the event"/>
    <aura:attribute name="name" required="true" type="String" 
                    description="Progress bar name"/>
 <aura:attribute name="action" required="true" type="String" 
                    description="Progress bar action"/>
</aura:event>

ProgressBarMessageEvt

<aura:event type="APPLICATION" description="Outboud event to guide the progress bar" >
    <aura:attribute name="value" type="Integer" default="" 
                    description="Value of the event"/>
    <aura:attribute name="name" required="true" type="String" 
                    description="Progress bar name"/>
 <aura:attribute name="message" required="true" type="String" 
                    description="Progress bar message"/>
</aura:event>

Both messages are really similar. Both have a name attribute to understand which progress bar should trap / fire the event, and a value attribute that has the value of the event.
The ProgressBarActionEvt has an action parameter that could have the following values:

  • Increment: increment by the value passed
  • Decrement: decrement by the value passed
  • FullFill: fullfills the progress bar
  • Reset: resets progress bar’s value
  • SetValue: sets a specific value

The app calls these actions in its controller’s button functions:

//...
increment10_p1 : function(component, event, helper) {
 helper.sendMessage("Increment","pb1",10);
},
//...

And in its helper:

({
 sendMessage : function(message,name,value) {
  var incrementEvt = $A.get("e.c:ProgressBarActionEvt");
        incrementEvt.setParams({
            name: name,
            value: value,
            action: message
        });
        incrementEvt.fire();
 }
})

On the other side, when we want to handle a message from the progress bar to the container app, we attach a handler to the event:

<aura:application>
    <aura:handler event="c:ProgressBarMessageEvt" 
                  action="{!c.handleProgressBarEvent}" />
 <!-- ... -->
 <div id="{!globalId+'_msg'}" />
//...
handleProgressBarEvent  : function(component, event, helper){
 var originName = event.getParam("name");
 var message =  event.getParam("message");
 document.getElementById(component.getGlobalId()+'_msg')
   .innerHTML = message+" event for progress bar named '"+originName+"' at "+(new Date()).toLocaleString();
},
//...

So every time a ProgressBarMessageEvt event is fired, the apps catches it and write down some of its info into the given DIV HTML component.

Finally let’s see how the component is constructed.
First we need to load jQuery and Bootstrap libraries and the required stylesheets:

<aura:component >
 <ltng:require scripts="/resource/BootstrapSF1/js/jquery-2.1.1.min.js,
             /resource/BootstrapSF1/bootstrap320/js/bootstrap.min.js,
             /resource/BootstrapProgressbar/bootstrap-progressbar.min.js"
        styles="/resource/BootstrapSF1/bootstrap320/css/bootstrap.min.css,
                /resource/BootstrapProgressbar/bootstrap-progressbar.min.css"
     afterScriptsLoaded="{!c.onInit}"/>
 
 <aura:handler event="c:ProgressBarActionEvt" action="{!c.handleEvent}" />
 <aura:registerEvent name="progressBarMsgEvt" type="c:ProgressBarMessageEvt"/>
 
 <!-- ... -->

And then define the place where the Bootstrap Progressbar will be drawn:

<!-- ... -->

<div class="{!'progress '+v.barContainerClass}">
 <div id="{!globalId+'_progbar'}" class="{!'progress-bar '+v.barClass}" 
   role="progressbar" 
   data-transitiongoal="{!v.value}"
   aria-valuemin="{!v.valueMin}"
   aria-valuemax="{!v.valueMax}"></div>
</div>

<!-- ... -->

This component will be fully configured by the “onInit” function of the component’s controller (that is called once all JS/CSS files are loaded):

//...
onInit : function(component, event, helper) {
        $("[id='"+component.getGlobalId()+"_progbar']")
        .progressbar({
            display_text: 'center',
            transition_delay: component.get('v.transitionDelay'),
            refresh_speed: component.get('v.refreshSpeed'),
            display_text: component.get('v.displayText'),
            use_percentage: component.get('v.usePercentage'),
            done : function(cmp){
                $A.run(function(){
                    if(component.get("v.value") >= component.get("v.valueMax")){
                        var evt = $A.get("e.c:ProgressBarMessageEvt");
                        evt.setParams({
                            name: component.get("v.name"),
                            message: "MaximumReached",
                            value: component.get("v.value")
                        });
                        evt.fire();
                    }
                    if(component.get("v.value") <= component.get("v.valueMin")){
                        var evt = $A.get("e.c:ProgressBarMessageEvt");
                        evt.setParams({
                            name: component.get("v.name"),
                            message: "MinimumReached",
                            value: component.get("v.value")
                        });
                        evt.fire();
                    }
                });
            }
        });
    },
//...

The done handler of the progress bar is used to fire the ProgressBarMessageEvt when the bar reaches min o max values.

handleEvent is the controller’s function that handles an incoming action event:

//...
 handleEvent : function(component, event, helper){
        var targetName = event.getParam("name");
        if(targetName !== component.get("v.name")) return;
        var targetIncrement = event.getParam("value");
        var action = event.getParam("action");
        var value = component.get("v.value");
        if(action === 'Decrement') value -= targetIncrement;
        else if(action === 'Increment') value += targetIncrement;
        else if(action === 'FullFill') value = component.get("v.valueMax");
        else if(action === 'Reset') value = component.get("v.valueMin");
        else if(action === 'SetValue') value = targetIncrement;

        var pb = $("[id='"+component.getGlobalId()+"_progbar']");

        if(value = component.get("v.valueMax")){
            value = component.get("v.valueMax");
        }
        component.set("v.value",value);
        pb.attr("data-transitiongoal",value).progressbar();
        
    },
//...

It simply checks progress bar name’s, action, value and executes the corresponding action.

The last command “redraws” the progress var with the new value, and executed the animation.

This is an example of fully javascript components you can make wrapping up existing javascript plugins.

Enjoy this component and may the Force.com be with you!

[Salesforce / Trailhead / Winter16] The Lightning fever: follow the trailhead!

Excited about the latest Lightning Experience announcement?

Me too but unfortunately it was published when I was on vacations without any internet connection, that’s why I read it days after its release, but I just thought “WOW!”.

with great power comes great responsibility, and the guys at Salesforce.com knows it, so they created some cool Trailhead modules to get you started, whether you are a developer, admin or a user.

Learn about why and how you can migrate to the new Lightning Experience, which are the differences and enhancements that has been made.

Watch the new Setup menu in action, saless tools, reporta and dashboards, customize the User interface and plan your rollout strategy: you can even decide which user will be using the new Lightning experience!

These set of modules are useful to understand user management, reports and dashboard creation, app customization (layouts, objects, fields) all with the new Lightning Experience interface.

If you are an experienced Salesforce.com admin you may find some of these modules way too easy, but I bet you’ll still find some new feature you didn’t know/expect!

Developers! That’s what we (most of us?) are!

These modules help you dig into the Lightning Experience as a developer: how can you use the Lightning Components? Is Visual Force dead (don’t worry, the answer is NO)?
The best feature IMHO? The Lightning Design System, finally a unique set of styles and HTML components to build custom applications with a look and feel that is consistent with Salesforce core features — without reverse engineering Salesforce styles!

…Without reverse engineering Salesforce styles!!!!

Finally some cool hints for users and how to use the new Lightning Experience interface (standard objects, list views appearance, dashboards, reports and feeds).

Next step (as usual)?

[Salesforce / Lightning Connect] Lightning Connect Custom Adapters and MongoDB

This is a repost of the article I published on Salesforce Developer Blog.

Summer ’15 Platform Release brought us the awesome Lightning Connect Custom Adapters: you can connect to external data sources and use them as custom Salesforce Objects writing custom Apex code.

After I read Introducing Lightning Connect Custom Adapters by Lawrence McAlpin, I wanted to get my hands dirty and try to implemented my own version of the adapter thinking of a “pseudo-real” use case.

If you are a TL;DR person, here is the code:

  1. Salesforce classes
  2. heroku-crest MondoDB NodeJS proxy

At first the DataSource namespace documentation has been published here, this way you can understand all the objects / interfaces / methods we’ll be using in this example.

In my use case we have:

  • A MongoDB server which stores several invoices
  • A NodeJS server that proxies Salesforce / MongoDB hosted on Heroku
  • A Custom Adapter implemented in Salesforce

The Data Model

An external system writes invoices records on the MongoDB server, storing data on the invoices table, following the model (you can simulate it by POST requesting on the following Heroku REST service):

{
    "_id": "55abc13dad230b03001d7edf",
    "contractid": "C20150001",
    "accountid": "ACC20150001",
    "created": "2013-10-25T20:15:45.851Z",
    "amount": 1000,
    "description": "invoice #1"
}

Where:

  • contractid: is a custom external id for the Contract object
  • accountid: is a custom external id for the Account object
  • _id: MongoDB id
  • created: is the created date (date/time field)
  • amount: is the amount of the invoice (number)
  • description: is a generic description

MongoBD REST interface

The next step is to give MongoDB a REST interface.
I’ve changed an old Project by Ricard Fredin, adding support for:

  • Basic authentication
  • Environment variables for MongoDB host name and port
  • Added support for $oid, $date and $regex BSON types
  • Support for Heroku Button

This is the updated repository with all the infos of the current changes and original project of the new Heroku Crest project.

This project comes with an Heroku Button:

Deploy

This means you can easily deploy this MongoDB proxy on your personal Heroku account:

You need to set your app name, the host name and the server port.

Let’s populate the DB

The last thing to do is to create at least one database on your MongoDB server with one valid user (with at least read permissions) and one table.

In our example we have a “lighthningconnect” database with an “invoices” table.

To see if your Heroku app works, make a get request:

GET https://[YOUR_HEROKU_APP_NAME].herokuapp.com/lighthningconnect/invoices
   Headers: 
   Authorization: BASIC [BASE64(username:password)]

You can also use POST/PUT/DELETE methods.

To populate your instance, make a post request of this kind:

POST https://[YOUR_HEROKU_APP_NAME].herokuapp.com/lighthningconnect/invoices
   Headers: 
     Authorization: BASIC [BASE64(username:password)]
     Content-Type: application/json

BODY:

{
    "contractid": "C20150001",
    "accountid": "ACC20150001",
    "created": {"$date" : "2014-09-15T20:12:42Z"},
    "amount": 1230,
    "description": "invoice #X"
  }

Once the MongoDB REST interface is set up, we are gonna create a new Salesforce Named Credential: this way we can setup access to the REST server (and MongoDB server) with a simple configuration on the interface, every time we make a callout to this endpoint:

The Lightning Custom Adapter implementation

The whole code of the Salesforce implementation can be found here.

The implementation is similar to the one of Lawrence McAlpin’s post.

The main modification involves the handling of the named credential and MongoDB database and table names.

Open the MongoDBDataSourceConnection.cls file and change the first lines:

private static String NC_NAME = 'MongoDB'; //Name of the Named Credential
   private static String DB_ENDPOINT_NC = 'callout:'+NC_NAME+'/lighthningconnect/invoices'; //database and table name in your own database

If you want to change the mappings, you can do it easily by modifying the following map:

private static Map FIELD_MAP = new Map{
         'Id' => '_id',
            'ExternalId' => '_id',
            'DisplayUrl' => '_id',
            'Account' => 'accountid',
            'Contract' => 'contractid',
            'CreatedDate' => 'created',
            'Amount' => 'amount',
            'Description' => 'description'
    };

And the sync() method:

override global List sync() {
        List tables = new List();        
        List columns = new List();
        
        // Always declare these two fields.
        columns.add(DataSource.Column.text('ExternalId', 255));
        columns.add(DataSource.Column.url('DisplayUrl'));
        
        columns.add(DataSource.Column.text('Description', 255));
        columns.add(DataSource.Column.text('Contract', 255));
        columns.add(DataSource.Column.text('Account', 255));
        columns.add(DataSource.Column.number('Amount', 16, 2));
        columns.add(DataSource.Column.get('CreatedDate','Created Date','', true, true, DataSource.DataType.DATETIME_TYPE, 255,0,null,null));
        
        tables.add(DataSource.Table.get('MongoDB_Invoice', 'ExternalId', columns));
        return tables;
    }

Finally we can analize how the query is really done using the REST proxy we just installed on Heroku:

private List<Map> execQuery(string soqlQuery) {
        List<Map> rows = new List<Map>();
        HttpRequest request = new HttpRequest();
        request.setEndpoint(DB_ENDPOINT_NC+soqlQuery);
        request.setHeader('Content-Type','application/json');
        request.setMethod('GET');
        request.setTimeout(60000);
        Http h = new Http();
        HttpResponse response = h.send(request);
        if(response.getStatusCode() != 200){ 
            return new List<Map>();
        }
        
        List result = (List)JSON.deserializeUntyped(response.getBody());
        for(Object obj : result){
            Map jsonObject = (Map)obj;
            Map row = new Map();
            row.put('Amount',jsonObject.get('amount'));
            row.put('Description',jsonObject.get('description'));
            row.put('Contract',jsonObject.get('contractid'));
            row.put('Account',jsonObject.get('accountid'));
            row.put('CreatedDate',parseDateTime(String.valueOf(jsonObject.get('created'))));
            row.put('ExternalId', jsonObject.get('_id'));
            row.put('DisplayUrl', DB_ENDPOINT+'/'+jsonObject.get('_id'));
            rows.add(row);
        }
        return rows;
    }

Basically we do a GET HTTP callout to our endpoint (the Named Credentials will work as a charm to authenticate user) and parse the result to create the object that will be used to present the query result.

The getSoqlQuery() method has been modified from Lawrence’s implementation, in order to adhere to the Heroku Crest application requirements (a JSON input query): we support all basic filters and result ordering.

Configure the Data Source

Once we have uploaded the two  classes, we can configure the External Data Source:

Click on the Validate and Sync button to get the new External Object named MongoDB_Invoice.

Configure the External Object’s lookups

Next step is to link this External Object to actual Account and Contract records referenced by the “contactid” and “accountid” fields on the “invoices” table.

For this reason we will create two new fields on the Account:

and Contract standard objects:

Then we can change the Contract__c and Account__c fields on the MongoDB_Invoice__x external object to be indirect lookups: follow this article but you have to change the field types of both fields type to be Indirect Lookup instead of External Lookup.

This is what you get after changing field types:

This way each record of type MongoDB_Invoice__x that have a “Contact__c” field equal to Contact.MongoDB_Ext_ID__c will be linked to the Contract as if it were a standard lookup field (the same happens for the Account object).

Use the External Object on your app

Next step, create a new custom tab for the MongoDB_Invoice__x object (I’ve configured the “All” list view to show all fields):

You can sort all columns (here the Created Date field):

Click on an External ID value you get all object info:

Where the account:

And its related lists:

And the contract:

With its related lists:

Query External Objects

Finally there is an example of a complex query:

You can certanly improve this implementation and add better query handling, speaking as a pure developer, it’s been a real funny implementation. Can’t wait to see DML statements to be added as well!

Stay tuned for the next platform releases!

[Salesforce/ Lightning] inputLookup: the missing component

Or quick tips on how to implement your own inputLookup Salesforce ligthning component

This is a repost of the article I published on Salesforce Developer Blog.

Salesforce Spring ’15 release brought some brand new components ready to be used in your lightning apps. One of the missing components that could be useful for your apps is the input lookup component. The idea is to use a typeahead input field. We are going to user Bootstrap and the Twitter typeahead component.

The idea behind this implementation is that the user will type a search on the input field and the typeahead shows a list of the first 20 items for the given object and search string. On load, the component should also load the initial value of the “name” field for the given object, if an ID value is selected.

This is how the component will look:

For those of you who don’t want to read more and just use the component, jump to the inputLookup github repo.

To ensure proper script loading we will use RequireJS with the trick proposed in this blog post.

Let’s first have a look at the lookupInput component’s markup (github):

<aura:component controller="InputLookupController">
    
    <ltng:require scripts="/resource/RequireJS" afterScriptsLoaded="{!c.initTypeahead}" />
    <aura:handler name="init" value="{!this}" action="{!c.setup}"/>

    <!-- ... -->

    <!-- public attributes -->
    <aura:attribute name="type" type="String" required="true"/>
    <aura:attribute name="value" type="String" />
    <aura:attribute name="className" type="String" />
    <!-- PRIVATE ATTRS -->
    <aura:attribute name="nameValue" type="String"
                    access="PRIVATE"/>
    <aura:attribute name="isLoading" type="Boolean"
                    default="true"
                    access="PRIVATE"/>

    <div class="has-feedback">
        <input id="{!globalId+'_typeahead'}" type="text" 
               value="{!v.nameValue}" class="{!v.className}" 
               onchange="{!c.checkNullValue}" readonly="{!v.isLoading}"/> 
        <span class="glyphicon glyphicon-search form-control-feedback"></span>
    </div>
</aura:component>

It uses the “InputLookupController” Apex class (with required @RemoteActions).

The RequireJS components triggers “c:requireJSLoaded” event that actually makes the component load its bootstrapped Typeahead input field: note the absence of any custom namespace, that is replaced with the “c” default namespace (this is a Spring ’15 feature).

We also have an init method that ensures that all required parameters are set.

This component simply uses a “type” parameters (with the actual API name of the needed SObject) and a “value” parameter that stores the selected ID (or the loading ID).

At first we want to load on initialization (or when the value parameter changes) the content of the input (we want to see the “Name” of the pre-selected SObject and not its ID).

The initialization loading is done using the following “inputLookupController.js” method:

initTypeahead : function(component, event, helper){
        try{
            //first load the current value of the lookup field and then
            //creates the typeahead component
            helper.loadFirstValue(component);
        }catch(ex){
            console.log(ex);
        }
    }

This is the helper part:

loadFirstValue : function(component) {
        //this is necessary to avoid multiple initializations (same event fired again and again)
        if(this.typeaheadInitStatus[component.getGlobalId()]){ 
            return;
        }
        this.typeaheadInitStatus[component.getGlobalId()] = true;
        this.loadValue(component);

    },

    loadValue : function(component, skipTypeaheadLoading){
        this.typeaheadOldValue[component.getGlobalId()] = component.get('v.value');
        var action = component.get("c.getCurrentValue");
        var self = this;
        action.setParams({
            'type' : component.get('v.type'),
            'value' : component.get('v.value'),
        });

        action.setCallback(this, function(a) {
            if(a.error && a.error.length){
                return $A.error('Unexpected error: '+a.error[0].message);
            }
            var result = a.getReturnValue();
            component.set('v.isLoading',false);
            component.set('v.nameValue',result);
            if(!skipTypeaheadLoading) self.createTypeaheadComponent(component);
        });
        $A.enqueueAction(action);
    }

This piece of code simply calls the “InputLookupController.getCurrentValue” remote action that simply preload the selected record’s Name field (if any).

The “typeaheadInitStatus” property (see the full file code) is used to avoid multiple initialization of the component (the “createTypeaheadComponent” method is the method that is used to create the typeahead component: this must be executed only once!).

On the other side the “typeaheadOldValue” stores the current value, in order to understand if the value parameter is changed: this is extremely useful when some other part of the application changes the value parameters and so the component should refresh it’s inner value.

To achieve this simply see the “inputLookupRenderer.js” file:

rerender : function(component, helper){
        this.superRerender();
        //if value changes, triggers the loading method
        if(helper.typeaheadOldValue[component.getGlobalId()] !== component.get('v.value')){
            helper.loadValue(component,true);
        }
    }

This method is called every time the component is rerendered (e.g. when one of its parameters changes), and it constantly evaluates if the “value” parameter has changed since the last set; if this is true then we load again the component, without re-contructing it (“skipTypeaheadLoading” parameters of the loadValue function).

The typeahead is a simple porting of the Twitter Typeahead component with some changes, the most important of which is the call to the remote action that search (using SOSL) for all SObjects given the search term (“substringMatcher” function of the helper file):

// . . . 
    substringMatcher : function(component) {
        //usefull to escape chars for regexp calculation
        function escapeRegExp(str) {
          return str.replace(/[-[]/{}()*+?.^$|]/g, "$&");
        }

        return function findMatches(q, cb) {
            q = escapeRegExp(q);
            var action = component.get("c.searchSObject");
            var self = this;

            action.setParams({
                'type' : component.get('v.type'),
                'searchString' : q,
            });

            action.setCallback(this, function(a) {
                if(a.error && a.error.length){
                    return $A.error('Unexpected error: '+a.error[0].message);
                }
                var result = a.getReturnValue();

                var matches, substrRegex;

                // an array that will be populated with substring matches
                var matches = [];

                // regex used to determine if a string contains the substring `q`
                var substrRegex = new RegExp(q, 'i');
                var strs = JSON.parse(result);
                // iterate through the pool of strings and for any string that
                // contains the substring `q`, add it to the `matches` array
                $.each(strs, function(i, str) {
                    if (substrRegex.test(str.value)) {
                        // the typeahead jQuery plugin expects suggestions to a
                        // JavaScript object, refer to typeahead docs for more info
                        matches.push({ value: str.value , id: str.id});
                    }
                });
                if(!strs || !strs.length){

                    $A.run(function(){
                        component.set('v.value', null);
                    });
                }
                cb(matches);
            });
            $A.run(function(){
                $A.enqueueAction(action);
            });
        };
    }
    // . . .

This “complex” code is used to push the results from the “searchSObject” remote action to the typeahead result set picklist.

Finally you can add the component in your lightning app:

<aura:application >

    <aura:attribute name="id" type="String" default="" access="GLOBAL"/>
    <aura:attribute name="objNew" type="Contact" default="{'sobjectType':'Contact',  
                                                       'Id':null}" />

    <!-- ... -->

    <div class="well">
        <div class="panel panel-primary">
            <div class="panel-heading">Existent sobject</div>
            <div class="panel-body">
                <div class="form-horizontal" >
                    <div class="form-group">
                        <label class="col-sm-2 control-label">Contact</label>
                        <div class="col-sm-8">
                            <c:inputLookup type="Contact"  
                                         value="{!v.id}"
                                         className="form-control "/>
                        </div>
                    </div>
                    <div class="form-group has-feedback">
                        <label class="col-sm-2 control-label">Loaded contact</label>
                        <div class="col-sm-8 ">
                            <ui:inputText value="{!v.id}" 
                                          class="form-control"
                                          placeholder="Change id value"/>
                         </div>
                    </div>
                </div>
            </div>
        </div>

        <div class="panel panel-primary">
            <div class="panel-heading">New sobject</div>
            <div class="panel-body">
                <div class="form-horizontal" >
                  <div class="form-group">
                    <label class="col-sm-2 control-label">Contact</label>
                    <div class="col-sm-8">
                      <c:inputLookup type="{!v.objNew.sobjectType}"
                                    value="{!v.objNew.Id}"  
                                    className="form-control "/>
                      </div>
                  </div>
                 <div class="form-group has-feedback">
                    <label class="col-sm-2 control-label">New contact</label>
                    <div class="col-sm-8 ">
                        <ui:inputText value="{!v.objNew.Id}" 
                                      class="form-control"
                                      placeholder="Change id value"/>
                     </div>
                  </div>
                </div>
            </div>
        </div>
    </div>

</aura:application>

We have two components, the first one ‘s value is grabbed directly from the “?id=XXXX” query string parameters, while the second one has no value on load:

Finally you can easily test that everytime you change the “value” input text, the inputLookup component loads it’s new “name” field, while if you search for a Contact on the component and select a record, the value input is set with the new value.

You brand new custom input lookup component is served!

[Salesforce / Trailhead] The beginning of your Force.com journey

a{color:red !important;}

Few days ago the Salesforce team released 4 new Trailhead modules, and I decided finally to have a look at it…with my style.

What is my style?

I may say “all in” or “all or nothing” style.

I decided to do all the modules and see which topics were covered (and how deeply).

With year of Force.com development it’s been quite easy for me to complete in few hours all the modules, but I haven’t earned all the points available (I did some mistakes when answering to questions) and I must admint I also learned something (expecially in modules I don’t play a lot in my job).

After 16 modules I have to say this is a really good starting point to start learning the basics of the Force.com platform, and sometimes the documentation goes deeper than you could expect, covering important aspects that sometimes you find out only after months of “real world” practice.

The Trailhead modules page lists all the modules in alphabetical order, but you can follow the 3 steps on the Trailhead main page to have a better study order.

Recently some cool modules have been added:

  • Process Automation: you learn the basics of process automation and the new Process Builder and Visual Workflows tools, cool ways to get your complex processes up and running in few clicks!
  • Chatter Basics: this useful module teaches the basics of setting up Chatter on your org to improve social collaboration
  • Lightning Components: this is my favorite modulo above all, I love Lightning Components and can’t wait to see them out of the Beta stage. Learn base and advanced aspects of this new powerful framework
  • Visualforce Mobile: learn how to create slick and smooth visualforce pages on the Salesforce1 mobile platform

This is the complete list of available modules:

And (awesomely) these are “can’t wait” upcoming modules:

  • Reports & Dashboards: Build real-time reports and charts to visualize key business metrics
  • Apex Integration Services: Integrate with external apps using Apex REST and SOAP services
  • Asynchronous Apex: Write more efficient Apex code with asynchronous processing
  • Visualforce & JavaScript: Use JavaScript to enhance and customize your Visualforce pages
  • App Deployment: Learn best practices for team app development and lifecycle management

Stay tuned for more modules!

I’m gonna definitely suggest all my Company’s interns to start learning Force.com using Trailhead, a funny and awesome way to learn the Force!

And once for all:

Page 1 of 2

Powered by WordPress & Theme by Anders Norén