Recently, I have been giving a talk on the local Salesforce Developers group meetup concerning the React and Angular applications, why and how to use them in Salesforce Lightning.
Apparently, the more and more companies become interested in using the third party frameworks for Salesforce development to reduce their costs. That is why I also decided to share my thoughts on the blog.
For the past couple of years, I have been working a lot with Salesforce by building the React and Angular applications on this platform.
I will give a quick overview of the following things:
- What is its current state
- How to build Angular/React apps as a lightning component and communicate data with Salesforce
Let me start with a couple of examples.
In the first one, we had to develop a sales reports validation system to improve the business process and reduce the error rate.
Furthermore, each report might have thousands of lines, but usually, there is only one person who validates them and creates an invoice.
Eventually, at Flowhaven, we created an Angular app which allows easy navigation, sorting, and error highlighting. We implemented a pre-validation feature that can parse and validate the report against column names even before customer submitted it. All the processing and changes appear to a local app state. For instance, select all lines or performing a mass search & replace operation. As a result, we insert changes to Salesforce in a single action.
Another example, Flowhaven had to build a highly interactive design approval tool to allow a simple collaboration between the parties. It has multiple integrations with external data sources, e.g., users can store files on GoogleDrive or Dropbox.
The user can view images, leave comments on them, upload new versions and compare them.
Currently, we are also working on video files support and drawing functionality.
- Easier application state tracking and management. There is no need to utilize cookies, local and session storage to remember the state between pages.
- Scalability. It doesn’t matter how many users we have at the moment if we do most of the processing in the browser.
- Easier integrations.
- You can surpass the Salesforce limitations.
- Enhanced developer experience. Faster development cycle and time-to-market.
First and foremost, it improved a lot for the past couple of years, and I genuinely enjoy it.
We have a new version of the programming language. Currently, it is EcmaScript2017 (ES8). Starting from 2015, ES6 introduced the modules, constants, arrow functions, spread operators, deconstructors, class interface, string templating, a lot of stuff.
We have Redux. It is a predictable, immutable, meaning that it has no side effects, state container for JS applications. We use it as a single source of truth of the app, and it becomes easy to manage and test the application state.
What about the available frameworks?
The most prevalent these days are Angular and React. Last year there were a lot of discussions, and many argued about which one is better.
It might be a surprise for someone, but I don’t see a big difference between these two from the developer perspective.
Both of them are using the component architecture. Everything is a component, and you need to structure your app accordingly. Even more, the Salesforce lightning framework also inherited this approach.
Both can use the Redux, stateful and stateless components, which is more a concept.
React uses ES6 while Angular forces you to use TypeScript. As far as I know, many companies, for instance, Onninen, use TypeScript for React as well.
React uses functional programming paradigm, where Angular uses functional-reactive.
The most significant difference is that Angular is opinionated when React is unopinionated. Meaning that there is one, right, an Angular way of doing things which you have to follow, but in React you have to make own decisions.
React might be easier to learn for new developers. On the other hand, it’s also easier to make an architecture mistake.
I, personally, follow the simple principle:
Go with the framework which is more familiar to your team.
In our case that was Angular. We build applications on Salesforce platform and our engineers are working with Java and Apex, so Angular with its model and TypeScript looks more appealing to them, and they can better understand the code.
Also, I like that Angular has own dependency injection system, which is useful for large-scale apps.
In the meantime, I suggest checking out the great tools such as Chrome extensions for Redux, React, and Angular so that you can overview the app in a visual format and debug it with ease.
Also Angular has own command line tool which allows you to create, build and test app and its parts with the CLI commands.
Let’s get our hands dirty and take a look at our demo application.
We are going to build a simple web app and use it as a lightning component inside the lightning page app. We will display the list of all contacts on one page and user would be able to click on any contact to get more descriptive information.
Before we start, here you can find the source code for this demo app.
What would we need in general?
- Lightning application (page)
- Apex class
- Either Lightning component or Visualforce page to load the JS app
We can use lightning components inside lightning apps. Nevertheless, we also could use Visualforce pages. That is why I would like to start with the simplest option.
First of all, we need to create a lightning app either via the app builder or programmatically. Then create a Visualforce page and make it available for lightning by checking the “Available for Lightning Experience, Lightning Communities, and the mobile app.”
When building a third-party framework web application in Salesforce, there are three ways to communicate with Apex:
- Remote Actions
- Web Services
- REST API
For our application we want to have two methods, one will send the list of all contacts, and another will give the detailed information for a selected one.
We would need to create an Apex class to hold the required methods.
Let’s name it AngularPOC.
I would like to start off with the Remote Actions. To do so, we should annotate our methods accordingly, with a @RemoteAction.
To make them invokable, we need to implement the controller on the Visualforce page.
Here is an example of how can we use it inside Angular application.
If you are using the TypeScript, you should first declare the global variable.
The second way to communicate data to Salesforce is using Web Services.
There are two main differences, all the web services are available globally, meaning that we can use any web service method from any class, plus they are synchronous.
Firstly, we need to update the Apex class by making it global and annotating the web service modifier.
Web services send data as is and we have to convert it to the JSON format manually.
Then we need to remove the controller from the Visualforce page and import SOAP libraries provided by Salesforce. When we include these libs, we get access to a sforce global variable.
To use the SOAP API, we need to pass a Salesforce access token along. So, we have to assign it to the sforce interface.
Then we can use this var to make a call.
Web service call is synchronous request via the SOAP API.
Since the call is synchronous, we want to use the try-catch block to handle errors. Although to make the call asynchronous we can use new async-await syntax introduced in ES2017.
The third way is using the REST API.
REST is the most convenient way for the React and Angular applications to retrieve data from the server.
The good thing is that we don’t have to rely on Salesforce abstractions.
Nevertheless, it has own drawbacks. For instance, sometimes in lightning experience, Salesforce redirects requests and changes the POST method to GET.
There are also few additional notes:
- You might need to whitelist your domain in the CORS settings
- You need to register a custom endpoint via the @RestResource annotation
- Each Rest Resource can have only one method of each type: HttpGet, HttpPost, HttpPut, HttpPatch, and HttpDelete.
In this example, I will use one HttpGet method for both contacts list and contact info.
If there is a contact Id parameter, we will return its information, otherwise, return the list of available contacts.
Inside the Visualforce page, we no longer need to load the SOAP libs but we still need to provide the access token which we will send with every request.
Then all we need is to make the Http request and set access token in Headers. Here is an example of using the Angular’s HttpClient service.
So far, we’ve learned how to use the Visualforce page as an iframe inside the lighting application, but there is an alternative.
Winter ’18 release brought us a new way to use third-party frameworks inside the lightning experience. It is called lightning container.
It is an interface which allows you to load a third-party web application from the static resource inside the iframe element and provides cross-domain access.
In the next release Salesforce is planning to block REST calls from the lightning containers. However, it is not clear what that would mean in practice.
Technically, all you need to do is to build the application, archive the distribution directory, upload it to the static resource and specify an index.html file as a source of the lightning container.
Utilizing the SFDX and building scripts gives you an option to automate the whole process to improve the development process.
The lightning container provides a new way of data communication between custom app and component besides the previously mentioned options.
It is possible to pass the data back and forth via the message event.
I won’t touch this method in the article because it is not the favorable way of data transfer for several reasons.
- You have to pass data twice. First, from the Apex to component and then from lightning component to container.
- Not developer-friendly API. It is harder to implement compared to other options.
- It fails silently, so it’s harder to do debugging.
Anyway, if you want to try this, you can find the source code for that approach in step/4 branch of the demo repository.
Also, recently I noticed the problem with the interface for the Remote Actions. The Visualforce variable is no longer accessible. So, I didn’t include that method in the article either.
So, at the moment, we have two options, either web services or REST.
Let’s see how can we use the web services inside the lightning container.
First of all, instead of a Visualforce page, we need to create a Lighting Component and reference the index.html file.
Apex controller will be the same as in a Visualforce example.
Then we need to include the SOAP libraries in the index.html file. We do not longer need the Visualforce page anymore, just a plain HTML.
There is a lightning container wrapper available as an NPM package to make things easier.
Install it by running
npm i lightning-container.
Now we can import this package into our app and use its interface to get the session Id because we no longer can use Visualforce expressions.
If you are using web service call inside the Angular application without Redux the change detector won't get the notification about changes. So, you would need to call the detect changes method after the call to explicitly rerender the UI.
Using the REST API services is entirely identical the example from the Visualforce. The only difference is that instead of passing session Id via the global variable you can get it inside application via the lightning container package.
Indeed, using Angular and React applications for Salesforce helps companies to reduce development costs, improve performance, bypass the platform limitations, etc.
In conclusion, there are three most convenient ways to do it: Remote Actions, Web Services, and REST API.
Web Services might not be the best options because it is using the synchronous call which is affecting the user experience. Plus, you have to use try-catch blocks to handle server errors and stringify the data.
Call to action
Afterward, if you want to know how to improve the user experience, performance, surpass the limitations and reduce costs of your Salesforce and SAP applications, contact me for a free consultation.
Phone: +358 41 471 6220