
How to Develop Salesforce Visualforce Apps Using AngularJS?
If you are looking forward to displaying Salesforce data to people without exposing your data to third party systems then Visualforce pages are your best solution. It gives provision for viewing, editing, and adding data without any third party interference, and as from the developers point of view creating Visualforce apps is a lot easier than some ad-hoc third party app calling Salesforce data.
Salesforce expanded and so did the popularity of Visualforce. With the launch of its support for jQuery, it changed the entire game. Another milestone was crossed when Salesforce gave the provision for JavaScript remoting for Apex Controllers. JavaScript remoting gave you the ability to access server side apex controller methods via JS directly, so this enhanced the flexibility and dynamic usage of Visualforce pages resulting in the higher adoption of the tool. And eventually, the number organizations using Visualforce pages to display data to their partners and clients increased. This definitely called for a much more appealing UI for the Visualforce pages, and AngularJS being everybodyâs favorite was chosen for creating the alluring and dynamic Visualforce pages.
How to Use AngularJS in Visualforce?
JavaScript gained momentum because of its success in frameworks and due to a higher demand of visually appealing, mobile-friendly single page applications. In Visualforce, the backend is not that flexible but the frontend is. So a framework like AngularJS is greatly preferred to create structured applications having excellent response times. Considering that each Visualforce app revolves around the four functions of create, read, update, and delete on Salesforce data there are three distinct approaches to binding the Salesforce data to Visualforce controllers.
- Creating and using JavaScript Remote objects with Visualforce.
- Using ForceTK libraries along with AngularJS libraries.
- Using JSON.
Visualforce page is lucid because you can start coding without opening or uploading multiple files to a server. We will proceed further with an example, in which we are going to fetch a list of Contacts from Salesforce and add a search function exhibiting two-way data binding.
Visualforce Main Page:
<apex:page showHeader="false" Controller="ContactsController">
<script src="https://ajax.googleapis.com/ajax/libs/AngularJS/1.3.14/angular.min.js">
</script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" />
<script type="text/javascript">
var app = angular.module('MyApp',[]);
app.factory('VFRemotingFactory',function($q,$rootScope){
var factory = {};
factory.getData = function(searchText){
var deferred = $q.defer();
GetAllContactsByFilter(function(result){
$rootScope.$apply(function(){
deferred.resolve(result);
});
}, searchText);
return deferred.promise;
}
return factory;
});
function GetAllContactsByFilter(callback, searchText){
if(searchText == undefined)
{
searchText="";
}
Visualforce.remoting.Manager.invokeAction(
'{!$RemoteAction.ContactsController.GetAllContactsByFilter}', searchText,
callback,
{escape: false}
);
}
app.controller('myController',function($scope,VFRemotingFactory){
$scope.mcm = {};
$scope.getFilteredData = function($event){
if($scope.mcm.searchText.length > 1)
{
var searchTxt = $scope.mcm.searchText;
VFRemotingFactory.getData(searchTxt).then(function(result){
$scope.ContactData = result;
});
}
else
{
var searchTxt = $scope.mcm.searchText;
VFRemotingFactory.getData().then(function(result){
$scope.ContactData = result;
});
}
};
$scope.Prafull = {};
VFRemotingFactory.getData().then(function(result){
$scope.ContactData = result;
});
});
</script>
<div ng-app="MyApp">
<div ng-controller="myController">
<label>Search: <input ng-model="mcm.searchText" ng-keyup="getFilteredData($event)"/></label>
<table class="table">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Phone</th>
<th>Email</th>
<th>Title</th>
<th>Account Name</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="contactVar in ContactData">
<td>{{contactVar.FirstName}}</td>
<td>{{contactVar.LastName}}</td>
<td>{{contactVar.Phone}}</td>
<td>{{contactVar.Email}}</td>
<td>{{contactVar.Title}}</td>
<td>{{contactVar.Account.Name}}</td>
</tr>
</tbody>
</table>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
</apex:page>
Letâs analyze this code. It starts by including a custom Salesforce apex controller <https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/pages_controller_custom.htm> for pulling through the contacts that we named âContactsControllerâ. This custom controller is also very simple.
public class ContactsController {
@RemoteAction
public static List<Contact> GetAllContactsByFilter(String searchText)
{
String searchString = '%' + searchText + '%';
List<Contact> contactList = [SELECT FirstName, LastName, Phone, Email, Title, Account.Name FROM Contact where FirstName like :searchString];
return contactList;
}
}
Here we are using JS Remoting to access to pass on our data. It is started by creating our first AngularJS module that answers to name âMyAppâ, var app = angular.module(âMyAppâ,[]). The particular app is referenced in the main body div via <div ng-app=”MyApp”>.
In the main body, the input box so created defines the things that we need to display. By default, the content is ââ which triggers to display all the contacts. As for the search function, when we start typing in the search section it starts to filter out the data in real time based on the value entered in the same page without the need for refreshing. The main Angular controller that is named âmyControllerâ is the main brain behind the appâs operations and that is included in the nested div of the body. Subsequently, create a module factory that triggers âGetAllContactsByFilterâ function. That function will now, in turn, invoke Visualforce remote objects and the Visualforce controller ContactsController. This factory is responsible for returning the list of contacts based on the search text, which by default is blank.
A scope object is created named âmcmâ that has the model data that we input through Search input field and the $scope is the main element that binds view with the model. On the other hand, ângâ function ng-keyup= getFilteredData($event) that is referenced in search input, triggers a new event whenever a key is entered in the search box. When the triggering of this event is done it results in automatic changing of model and view.The AngularJS controller âmyControllerâ, triggers fetching of data based on the input value. For the blanks it fetches all data so does it for typing only single alphabet. The data that is fetched is stored in scope object â$scope.ContactDataâ which subsequently passes the data to âcontactVarâ that finally displays data.
On an ending note letâs summarize how AngularJS unleashed its full potential in this small and basic example:
- The ng-keyup triggers any event based on user input. A custom function for this the trick is at its peak.
- The two-way data binding using custom code is an entire day work but it helped us to get through in an hour.
- ng-repeat, the function used to pre-populate the table. On the contrary, a custom code for the same will take 3 to 4 hours in the least. But, AngularJS helped us to complete it within a blink of an eye.
- In order to add automatic filters we just had to add a line in the ng-repeat reference.
For example, if we need to filter out by âan accountâ we just have to add ng-repeat=âcontactVar in ContactData | filter:accountâ.
(We are assuming that the âaccountâ is a predefined variable).
In short, AngularJS combined with the power of Visualforce form a significant platform. There are other methods to put forward and exhibit the same functionalities, but as of now, I have discussed the best one for you to go ahead and explore.
Credit: Source link