SFDC Stop - Always the latest about Salesforce


Full Tutorial Series with videos, free apps, live sessions, salesforce consulting and much more.


Telegram logo   Join our Telegram Channel
Showing posts with label React JS. Show all posts
Showing posts with label React JS. Show all posts

Sunday, 26 August 2018

Embed your custom javascript application in Salesforce using Lightning Container

Hello Trailblazers, In this post I am going to tell you, how you can embed a custom javascript application made using any Js framework like:- React Js, Angular Js etc. within Salesforce Lightning Component. This post is a follow-up for my session at Jaipur Developer Fest 2018. I am going to give you all the resources required to get started with this concept as well as tell you a brief description about Lightning Container and it's implementation. As I have worked on React Js before switching onto Salesforce, I am going to make a sample React Application for the demo. Before moving ahead, let's have a look at presentation first:-

The lightning container component hosts your custom JavaScript application in an iframe within your lightning pages. As described before, you can embed any js application in salesforce lightning component using lightning container.

What is the need of Lightning Container ?

Traditional methods focus on using an iframe to embed a third party javascript application in salesforce and use that. Below are some common questions that arises using this traditional approach :-
  1. Why host that application onto some other server ? Use iframe to connect with that even if I need to use it within Salesforce Org only ?
  2. Why develop and use custom Salesforce APIs for data sync when I have other better methods to connect with Salesforce ?
Another common reason can be:- even with the evolution of Lightning, most Salesforce Developers use custom js frameworks to build UI and move towards a better looking visualforce page. However, I'll suggest you to move to Lightning because this is the best thing you can do but still Salesforce has now given you a platform to build your application in js framework of your choice and embed that in Lightning Component to use.

Features of Lightning Container

  1. Lightning Container allows you to use an application developed in 3rd party framework like:- Angular, React Js etc. in Lightning Component.
  2. Lightning Component can handle messages as well as errors from your embedded app in it's controller.
  3. In the same way as above, the embedded javascript application can also handle messages as well as errors, from your lightning component
  4. You can also call apex from your custom lightning:container application

Lightning Container Implementation

If you want to gain more theoretical knowledge about Lightning Container, kindly refer to the above presentation as now we're going to dig deep into code and embed a sample react application in Lightning Component. As we're going to develop a react application, there are some pre-requisites for your system:-
  1. You must have nodejs installed into your system, download it from here
  2. npm (node package manager) is automatically installed when you install nodejs.
  3. Download and install git from here.
I have made a full boilerplate code for you to get started with Lightning Container along with the sample implementation of all the methods available.

Once you have nodejs and npm installed, next step is to star my github repository so that you don't lose access to it in future and clone it using the command below github repository :-

Open Git Bash or cmd and use the above command to clone my boilerplate repository into your system. Once you have my repository cloned, switch to lightning-container-boilerplate directory and hit npm install command. (To switch in windows, use cd lightning-container-boilerplate and hit enter in the command line when you have cloned the repository successfully).

npm install command will install all the dependencies needed by our react boilerplate application and also the dependencies needed by our js app to connect with Salesforce. Salesforce has provided easy to use npm modules to use in your custom js app to establish a connection between both. A brief description about the npm modules is given below:-

  1. lightning-container:- This npm module is a must have to establish the communication between your javascript application and lightning component. It consists of methods like:- sendMessage, callApex, addMessageHandler, addErrorHandler etc.
     
  2. @salesforce-ux/design-system:- This module consists of all the slds classes that we can use in our custom js application to give it a proper look and feel of lightning.
Once you have cloned the github repository and installed the dependencies, you need to hit npm start command. Once you type this and hit enter, your react application will start running on port 3000 and you'll have something like given below:-


This is our react application that we're going to embed in lightning component using lightning:container. You'll see a build/ folder into your base lightning-component-boilerplate folder. Now, we have to zip this build folder and upload it as a static resource in Salesforce. While you're uploading it to your salesforce org, just make sure that you give the static resource name exactly as lightningcontainerboilerplate. This is because our lightning component can only find our application with this name. If you see in the base (lightning-component-boilerplate) folder, we have an .env file that consists of the below content:-

As you can see above, we're specifying our static resource name in the PUBLIC_URL of our application so that it can be easily embedded. If you look at the contents of the base folder, we also have an apex folder there. That apex folder consists of all the apex code that we need to add into our Salesforce Org. If you explore the apex folder more, you'll see the src folder in that in which further will consist of 2 folders:- aura and classes. In the aura folder, I have made a lightning component named lightningcontainerboilerplate and to test that, I have made a lightning application too named lightningcontainerboilerplateapp. In the classes folder, I have a single class named LightningContainerBoilerplate which is called in our custom js application directly as an apex call.

Now, before moving to the code in custom js application, we'll have a look at the Salesforce code first.

LightningContainerBoilerplate.cls

Starting from the apex class, let's have a look at the below code:-

As you can see above, we have a single function in this class which returns a String and has a @RemoteAction annotation that takes a single parameter called name and insert a contact with the LastName of contact equal to the name passed in the parameter. After the contact is inserted, we're returning a string consisting of message - Contact inserted successfully along with the contact id. This method must have a remote action annotation then only we'll be able to call it from our custom js application and it should be global and static too.

LightningContainerBoilerplateApp.app

Now let's have a look at our app, as you can see that we have just called our lightningcontainerboilerplate component and our app is extending force:slds so that we can easily apply and use slds in our lightning component.


LightningContainerBoilerplate.cmp

Let's have a look at the code below:-

As you can see above, I have made a simple lightning component that I can embed in lightning pages, I have made a single attribute named myMessage which is of type String and displays the message received from the custom js react application. Then I have made two lightning cards, one has a title Lightning Component and other has a title JavaScript Application.

Lightning Component

I have divided the Lightning Component card into 3 parts as follows:-
  1. In first part, I am displaying myMessage attribute using {!v.myMessage}. This is the message received from react application.
  2. In the second part, I am displaying an input field with a label of Input Message and an aura:id as inputMessage in which I can input the text to send to my react js application.
  3. In the third part, I have made a simple button with a label Send Message which is calling sendMessage controller function on click and is responsible to send the message to the react application.

JavaScript Application

In this card, I have simply called lightning:container tag in which I have given a class named containerClass which we'll define in css. We've given it an aura:id of jsContainer and in the src attribute, I need to give the reference to static resource. So, I have given it as {! $Resource.lightningcontainerboilerplate + '/index.html' }. There are two more attributes named as onmessage and onerror in which I need to call some controller functions as the onmessage attribute controller function will be called when a message is received from react app and onerror attribute controller function will be called when there is an error while receiving message from the js container. I have specified handleMessage controller function in the onmessage attribute and handleError controller function in the onerror attribute.

LightningContainerBoilerplate.css

As you can see above, I have defined the containerClass here used in lightning:container tag and specified a height of 400px for my custom js react application.

LightningContainerBoilerplateController.js

Now moving on to controller, let's have a look at the code below:-

As you can see above, handleMessage and handleError functions are responsible to handle the message and error from custom js application and were called from lightning:container attribute. Whereas, the sendMessage function takes the value of inputMessage (aura:id) input field and then send this value as a message to our react application using component.find('jsContainer').message(inputMessage); where jsContainer is the aura:id of lightning:container and message() is in the syntax to send any message to the container application.

React Js Application

Now, let's understand our sample react application that we used in this tutorial. This react application is made using create-react-app command. create-react-app is an npm module that you can install globally by using the command below:- 


You can find more information about this npm module here. You can create a new react application by using create-react-app as follows:-

create-react-app <application-name>

If you create any application using the above command and then move to that app's folder and run npm start, you'll see the below page:-


I have only modified the code in app.js file and the updated code is given below:-

As you can see in the above code,

  1. First of all, we've imported the lightning-container module and also the css file of slds from @salesforce-ux/design-system module
  2. In the constructor, I have initialized the state with two keys:- messageReceived and messageToSend. A state is basically a javascript object that we can use for interaction within a component. The messageReceived object mainly consist of a type and a value so that we can use the same object to display different types of messages received (success and error). I have also binded all the functions used in my application. It is a react syntax to bind all the functions to use them.
  3. In the componentDidMount() which is like an init method for react and is called as the component is mounted, I have called addMessageHandler and addErrorHandler methods from the LCC package and passed the handleMessage and handleError methods in them to specify the methods that'll be responsible to handle the message and error respectively coming from lightning component.
  4. The handleMessage method is receiving the message in a variable named successMessage, creating a javascript object with a type - success and value with the message received in successMessage variable.I am setting the messageReceived in state with the newly created messageReceived object using this.setState({ messageReceived: messageReceived }); 
  5. Similarly in the handleError method, I am setting the messageReceived in state in the same way, the only difference is here the object has a type of error.
  6. Next we have sendMessage() which is calling LCC.sendMessage() that can pass a javascript object as it's parameter. Here, our javascript object consists of two things, a name and a value where I have hardcoded name as MyMessage and value is this.state.messageToSend i.e. the value of this key in the component state. This value I am going to set as I take input in the input field.
  7. Now, let's move down to the HTML code returned inside render() It has slds applied and consists of simple title and then a form which consists of an input field for entering the Last Name and two buttons, one to send a message to lightning component and other to save contact. Both buttons use the input provided in the last name field.
  8. On change of input in the lastname field, I am calling this.handleInputChange. In this method, we're getting the value of input field using event.target.value and storing it in message variable and I am setting the messageToSend in state with that message variable using this.setState({ messageToSend: message }); 
  9. The Save Contact button is an input of type submit on click of which, the form is submitted and in the form tag, we're calling this.callApexController method onSubmit of that form. If you see the callApexController method, I am preventing the default behaviour of form submission using event.preventDefault and then I am using LCC.callApex() to call the apex controller directly from this JS application.
  10. In LCC.callApex I am passing 4 parameters, first is the class and method name LightningContainerBoilerplate.createNewContact, the second is this.state.messageToSend which I have set on change in Last Name input before. The third is this.handleApexReturnValue which is the callback method to be called when we receive a response from apex controller and the fourth is {escape:true} which is to maintain security to escape special characters so that no malicious js code is passed in response from apex.
  11. In the handleApexReturnValue method, we're getting two parameters as specified by salesforce, first is the result which is the value returned by our apex controller method and second is the event which is used to get the status of apex call. Next, I have created a variable named messageReceived and checking if the event.status is true then the messageReceived is equal to an object with type apexsuccess and value as result received from apex controller method. Otherwise if event.type is exception, then we have an object with type as apexerror and the value as event.message concatenated with event.where else we have an object with type as apexerror and value as event.message only as it is not an exception but any other unknown error. Finally, I am setting the messageReceived state with messageReceived object. 
  12. In the HTML code, below the form, we're checking the this.state.messageReceived.type and displaying different messages according to the state and then the value as this.state.messageReceived.value

If you make any changes, then to create a production build, you again open another terminal and move to the same lightning-container-boilerplate directory and run npm run build command. This will create a production build for application that we can upload as a static resource in our Salesforce Org and use it from there to embed in our lightning component. Once you've created a production build, you'll see a build/ folder into your base lightning-component-boilerplate folder. Now, we have to zip this build folder and upload it as a static resource in Salesforce.

Just make sure that, you append the above code in the manifest.json file generated in the build folder generated after creating a production build. If there is no such file, create one and add this code surrounded by { } which is the standard format of json file. This is required to specify that our custom js app is dealing with the apex controller which is mentioned in the code above and I have specified the apex-controller as LightningControllerBoilerplate which is the one I am using.

I hope you liked this blog and if you want this session to happen again or want a video about the same let me know in comments. Sharing a picture of my session at JDF below:-



Sharing my twitter moment below:-


And I am also embedding my first VLOG made at #JDF18. Do watch it and let me know if you liked it or any suggestions for further VLOGs :P



Happy Trailblazing..!!

Tuesday, 24 July 2018

Live Session on Lightning Container Component - Jaipur Developer Fest 2018

Hello Everyone,

I am very happy to share with you all that I'll be speaking at Jaipur Developer Fest 2018. This year, #JDF18 is happening on 28th of July, 2018 | 7:30 A.M onwards. This is an amazing opportunity for all of the amazing salesforce enthusiasts in India to connect with our Salesforce Ohana, learn more and take some of the most valuable insights and learnings with them back to their organization. Below are the details about my session and other activities :-

Embed your JavaScript application in Salesforce using Lightning Container


My session is scheduled from 3:30 P.M - 4:00 P.M. and the title of the session is "Embed your JavaScript application in salesforce using Lightning Container" as stated above. In this session I'll mainly show you a live demo of how you can run any JS application built using 3rd party frameworks like:- React, Angular etc. in your custom Salesforce Lightning Component.

But Wait..!! It doesn't end here. I have one more amazing thing to share.

Circles of Success

This year, the awesome people of JDF announced a new initiative called "Circles of Success". So, now the question arises that :-

What is COS ?

In simple terms, I can say that it is a round table discussion on a particular topic related to Salesforce consisting of 6-10 salesforce trailblazers like you and will consists of 1-2 Salesforce Experts. The best part is that you can come with your doubts regarding any Salesforce Topic for which the COS is scheduled and you can discuss with the expert regarding the same.



I'll be volunteering as an expert in Integration table. So, if you have any doubts regarding apex callouts and integration, postman or any other stuff related to same. You can come to my COS and have a one to one discussion with me. I'll put on my best efforts to help you for sure. The timings of my COS discussion is 1:00 P.M - 1:30 P.M.

For those who are outside and can't attend. My presentation and source code will be available in another blog post after the session for sure. For more information about the full agenda of JDF18 click here.

Hope to meet you at Jaipur Developer Fest very soon.

Happy Trailblazing..!!

Wednesday, 27 June 2018

Build Admin Friendly Custom User Interfaces Using Salesforce UI API

Salesforce User Interface API


I gave a live demo of Salesforce UI API at TDX18GG organized by New Delhi Salesforce Developer Group and Salesforce Gurgaon WIT User Group and in this blog post, I am going to give you all the resources of my session as well as a brief idea about Salesforce UI API and how you can implement it.

Let's have a look at the presentation first:-


Introduction to User Interface API

We already have a lot of APIs in Salesforce like:- Metadata API, Chatter Rest API, Tooling API etc. So the question arises that - Why Salesforce created UI API ?
To build Lightning Experience, the developers at Salesforce needed a new API because the existing APIs were designed for data integration not for building user interfaces. So, after discussions among themselves, UI API was born.

How UI API is different ?

UI API is developed specifically for building UI. Therefore, unlike other APIs which primarily focus on one particular thing, UI API gives you everything you need to build UI in one single package. It consists of the layout configuration, record data as well as metadata together to build custom and dynamic UI.

When you develop a custom UI, if you need to do any changes in the UI, you have to jump into the code to do that. Suppose, you need to swap two fields in the User Interface or remove a field, you need to go to the code and do the required changes right ? but with UI API, it's just a matter of few clicks..!!

As developers building Salesforce themselves used UI API to build lightning experience and they made their API public, so if you use UI API to create layout for your custom web or mobile application linked to Salesforce, it'll be synchronized with your UI at org automatically. This means that:-

If you do any changes in the layout in your Salesforce Org, the same changes will reflect in your custom UI automatically and it'll render automatically with the updated layout.

This is a very good and awesome feature of UI API, not only this, your sharing rules, field level security will be automatically handled by UI API itself i.e.

If a particular field is not visible in Salesforce to the user, it'll not be visible to the same user in your custom application using UI API.

Isn't that Amazing..?? But wait not only this, UI API provides you a lot more features listed below:-
  1. With UI API, you get the record information along with the layout information. That means you don't need to do any query to fetch the records separately in your UI.
  2. It provides you the data and metadata about the actions provided in the UI like custom buttons, quick actions etc. So that the custom buttons behave in the same way in your custom app to as they work in your salesforce org.
  3. You can easily perform CRUD operations on records with UI API.
  4. UI API makes it easier to implement dependent picklists in your custom UI by providing keys to match the records dependent on other records.

Live Demo - Salesforce UI API

I have given a live demo of UI API at global gathering but don't worry if you were not able to attend that. I am going to give you a brief demo about UI API now and provide you the whole code that I used in the demo. So, let's learn UI API step by step:-

To get started go to the workbench REST Explorer:- https://workbench.developerforce.com, choose your environment and click on login with Salesforce. Once you are logged in, you can navigate to the rest api explorer of workbench by hovering over the utilities option in the menu bar and then clicking on REST Explorer as shown below:- 


Once you are in the REST Explorer, you'll see a URL like this:- /services/data/v43.0/ in the text field with an execute button. It is used to hit any Salesforce API. Now we are going to hit UI API from this and will understand the response. Now, let's suppose I want to make UI for any record detail page that I need to show in my custom application. For this, copy and paste the given text in your text field:- /services/data/v43.0/ui-api/record-ui/<record-id> and hit Execute. Here, <record-id> can be the id of any record like:- account, contact that exists in your salesforce org. For example when I replace this <record-id> with the id of an account in my org, the final URL is as follows:- /services/data/v43.0/ui-api/record-ui/0017F00000qSAEy with the account id, and when I click on execute the final result is as given below:- 

As you can see in the above picture we have the following items in response:-
  1. eTag
  2. layoutUserStates
  3. layouts
  4. objectInfos
  5. records

eTag

eTag is basically used for HTTP Caching. If we want to reduce network traffic and increase our app's response time, we can make use of this eTag. The eTag is known as the Entity tag and it consists of a hash of a representation of our response and if that representation changes, a new eTag will be generated automatically. This means that if there are any changes in the layout or records or anything that is coming in the response, a new eTag will be generated otherwise the previous eTag will be there. In order to use this feature we can send the previous eTag in header while making another request so that if the response is the same, an HTTP 304 Not Modified response will be generated instead of the actual response data. To add eTag to the header, write like this:- 
If-None-Match: "3f443b7df24d5ee553e5b901fdfbf0ae"
 where If-None-Match is the header key to check the previous eTag while forming the response and after : is the actual eTag enclosed in "" (inverted commas). If there is no change the response will be like shown below:-


As you can see above, an HTTP 304 response will be given if the response is not changed i.e. any data present in the response is not updated.

This was a main concept of using UI API, the other response values are dynamic according to the request made and the response bodies can be understood by referring to the UI API original salesforce documentation. In our case, we are fetching the record UI whose response is explained in the documentation here. It is pretty simple to understand other response values while fetching record ui apart from eTag:-

  1. layoutUserStates:- Map of layout IDs to the user state information. Show whether each section in the layout is collapsed or not. Each section has a unique id.
  2. layouts:- A map  of object API names to the layout information of each object. It consists of whole description of the layout along consisting of every single data like which sections are collapsible and which field is present in which row and in which section, the number of columns in each section etc.
  3. objectInfos:- A map of object API names to each object's metadata. It consists of whole object metadata including:- fields, depend fields, child relationships, record types etc.
  4. records:- A map of record ids to each record's data. In the record-ui we provide the record id at the end, so the whole data in each and every field of that record will be given in this part. Record data is provided along with the api name of each field so that we can easily synchronize the whole data with the fields available and show in our custom layout.
Sharing rules and field level security are implemented automatically by the UI API depending upon the user hitting the API. (Try to turn off visibility of any field and then check that whether that field is in the response or not)

Moving on to React

I have also made a react application for my demo of UI API. You can clone the same from the github repository here. It consists of a very basic code to fetch the record layout with different fields that will change there position if you change the layout. So open your Git Bash, move into a directory you want to work in and execute the following commands:-
  1. git clone https://github.com/rahulmalhotra/SalesforceUIApi.git
  2. cd SalesforceUIApi
  3. npm install
  4. npm start

P.S.:- I am using a windows system and maybe the commands should be same inside the git bash on mac too but I don't have the right idea. Let me know in comments if there is something different for mac and I'll update this.

So, your react app will run and open in your browser at localhost:3000 port and you'll see something like below:-


Wow..!! Your react app is up and running. If you open the console, you'll see an error saying failed to fetch as the app was not able to connect to your salesforce org and fetch the account layout. To make it simple and to the point, I haven't used any oAuth or anything for authentication, If you move in to the src folder and then to the App.js, you'll see something like given below:-

So, as you can see in the above code snippet, in this.state I have hard-coded the access token and the account Id as I am fetching the account record, for the access token, you need to create a connected app in Salesforce and hit it by postman or any other tool and account Id is simply the id of any account in your org. Then you can see that in the render() I have simply given a heading - Salesforce UI API Demo with React and called ViewAccount component by passing the accountId and accessToken in that as parameters.

Note:- If you don't know how to create a connected app or get the access token via postman let me know in comments and I'll create a separate post for that too.

Now if you see ViewAccount component in the src folder, in the constructor, I have called fetchAccountDataFromUiApi() this method is hitting my salesforce URL by using fetch() and setting up the required info to send like the account Id is concatenated at the end of the URL, request type is GET and headers consists of 'Bearer ' along with the access token concatenated with that, you can change the domain to your own salesforce org domain. In the response, I have extracted the sections and fields from the api where sections are from layouts and fields are from records key of the UI API as we need both. In the render() again I have simply written This is a simple component to view account and then called the layoutSections() which is passing the sections and fields information to LayoutSections component.

In the LayoutSections component, it is extracting the rows from sections and passing the rows and fields to LayoutRows component.Similarly, in the LayoutRows component, it is extracting the fields in each row and mapping it's value by checking the api name with the fields data we have and displaying it in a div.

If you have set the access token, record Id and URL correctly, the final output will be as follows:-


So, as you can see, the Account Information is the section name is there and if I see my account layout in the org, it is as follows:-


As, you can see that in both the layouts, my rows contain data as follows:-

Account Owner -> Phone -> Account Name -> Rating and so on....

Now it's time for magic. Let's edit our account layout in the org so that it's like given below:- 



You can see now, that the rows contain data as follows:-

Rating -> Account Name -> Phone -> Account Owner and so on....

Now if I refresh my react application, I'll see something like this:- 


Now, as you can see that the fields are in the same order in my custom layout also when I changed the order in my Salesforce Org. This is the beauty of UI API. Although my layout is not much appealing and I am sorry for the same :P But, it works for demo right..!!

So, that's all for this post. Let me know if you have any queries or suggestions in comments section below.

Sharing a picture of my session below, hope to see you in the next one too.


Happy Trailblazing..!!