Build Salesforce Visualforce app using AngularJS

Posted on by

Salesforce is considered to be the worst technology for developers in 2015. However, it’s still number one CRM system in the world and is perfect for businesses. It’s fast, customizable and secure. Along with such JavaScript frameworks as AngularJS, you can build modern and useful web applications.

In this post, I will show you how to connect an Angular application to the Salesforce REST API.

BabelJS

I will be using the latest JavaScript standard in this tutorial – EcmaScript2015 (ES6) because it allows me to use such things as modules, arrow functions, and template strings. I am using BabelJS to compile my ES2015 JavaScript into ES5 code.

By the way, I’m very excited about TypeScript, because it’s recommended by the Angular team and they are using it in the second version. Nevertheless, I will stick with the ES2015 for now.

Prepare a Salesforce controller

We need JSON data for our application to be displayed. To accomplish that let’s prepare an Apex class file named SFAppController.cls. This controller will get data from the database and output it in the required JSON format.


public with sharing class SFAppController {
  public String heroesJSON {get;set;}
  public Hero__c hero {get;set;}

  public SFAppController() {
    heroesJSON = JSON.serialize(getHeroes());
  }

  public List<Hero__c> getHeroes() {
    List<Hero__c> hero = [SELECT id, name FROM Hero__c];
    return hero;
  }
}

Create an Angular application

Now, we have everything ready on the back-end and we can start building our Angular application. I am using a modular approach, so every component, service, and a filter have an own module. Let’s initialize our application first.


angular
  .module("SFApp", []);

Where should we load our data?

The angular team suggests using services for that purposes. This method fits in my modular approach and is easily maintainable. It’s also easy to use data in different controllers via services.

Create a service, name it heroes.service.js.


export default function getHeroes() {
  this.heroes = {!heroesJSON};
}

As you see, I’m using a Salesforce object. You can do it only if you load your JavaScript internally. I will return to this later when we will set up a Visualforce page.

Component

Now it’s time to create an Angular component, which will contain a template and controller function. Components are available since Angular 1.5 replacing directives.

I’m building my applications in an Angular 2 way, that’s why I’m using components over the directives.

Let’s name our component heroes.component.js. Don’t forget to inject our getHeroes(); service into component’s controller function.


export default {
  "template": `
    <ul>
      <li ng-repeat="hero in $ctrl.heroes">
        {{hero.name}} - {{hero.id}}
      </li>
    <ul>
  `,
  "controller": ["getHeroes", function sfHeroesCtrl(getHeroes) {
    this.$onInit = () => {
      this.heroes = getHeroes.heroes;
    }
  }]
}

Once we have our component and service set up, let’s import them and register in our Angular application.


import getHeroes from "./heroes.service";
import sfHeroes from "./heroes.component";

angular
  .module("SFApp", [])
  .service("getHeroes", getHeroes);
  .component("sfHeroes", sfHeroes);

Set up a Visualforce page

We have already prepared our Salesforce controller and Angular app. The next step is to put everything into Visualforce page.

What should we keep in mind?

1. Disable default styling;
2. Enable HTML5 mode;
3. Remove default HTML and Body tags;
4. Reference our Salesforce controller.


<apex:page standardStylesheets="false" sidebar="false"
showHeader="false" applyBodyTag="false" applyHtmlTag="false"
docType="html-5.0" controller="DASubmissionViewController">

We also need to load an Angular Core library. I’m using version 1.5 for this tutorial.


...
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>

The only thing left is to add our component to the body tag


...
<sf-heroes></sf-heroes>

and load our application script internally after Angular core.


<script>
  !function(e){function t(n){if(r[n])return r[n].exports;var o=r[n]={exports:{},id:n,loaded:!1};return e[n].call(o.exports,o,o.exports,t),o.loaded=!0,o.exports}var r={};return t.m=e,t.c=r,t.p="",t(0)}({0:function(e,t,r){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}var o=r(7),u=n(o),s=r(8),i=n(s);angular.module("SFApp",[]).service("getHeroes",u["default"]).component("sfHeroes",i["default"])},7:function(e,t){"use strict";function r(){this.heroes={!heroesJSON}}Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=r},8:function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t["default"]={template:'\n    
    \n
  • \n {{hero.name}} - {{hero.id}}\n
  • \n
\n ',controller:["getHeroes",function(e){var t=this;this.$onInit=function(){t.heroes=e.heroes}}]}}}); </script>

Final Visualforce page’s code


<apex:page standardStylesheets="false" sidebar="false"
 showHeader="false" applyBodyTag="false" applyHtmlTag="false"
 docType="html-5.0" controller="SFAppController">
  <html>
    <head>
      <title>Salesforce Visualforce Angular Application</title>
      <meta charset="utf-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1" />
    </head>
    <body ng-app="SFApp">
      <h1>Heroes</h1>
      
      <sf-heroes></sf-heroes>

      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
      <script>
        !function(e){function t(n){if(r[n])return r[n].exports;var o=r[n]={exports:{},id:n,loaded:!1};return e[n].call(o.exports,o,o.exports,t),o.loaded=!0,o.exports}var r={};return t.m=e,t.c=r,t.p="",t(0)}({0:function(e,t,r){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}var o=r(7),u=n(o),s=r(8),i=n(s);angular.module("SFApp",[]).service("getHeroes",u["default"]).component("sfHeroes",i["default"])},7:function(e,t){"use strict";function r(){this.heroes={!heroesJSON}}Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=r},8:function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t["default"]={template:'\n    <ul>\n      <li ng-repeat="hero in $ctrl.heroes">\n        {{hero.name}} - {{hero.id}}\n      </li>\n    </ul>\n  ',controller:["getHeroes",function(e){var t=this;this.$onInit=function(){t.heroes=e.heroes}}]}}});
      </script>
    </body>
  </html>
</apex:page>

That’s it! Now you know how to connect an Angular application with Salesforce REST API and display the data using Visualforce.

In future, I’m planning to write an article on building an Angular 2 Salesforce app using TypeScript and Webpack module bundler.

Meanwhile, you can check out my Angular Salesforce Webpack ES2015 boilerplate