AngularJS is a popular open source Web development framework located at http://angularjs.org. It is a powerful tool for using the MVVM pattern, or Model-View-Whatever (MVW) as Google prefers it, in your Web application. For example, you can take advantage of its bidirectional data binding to tie the application’s model to its view, making Angular responsible for keeping them in lockstep at all times. This type of tight data binding provides users an experience free of Refresh and Save buttons and confusing mismatches between the model and view.
The demonstration page shown in Figure 7.1 is adapted from steps 0 through 5 of the Angular tutorial available at http://docs.angularjs.org/tutorial. It retrieves a list of projects from the Force.com database and allows the user to order them by name or date created, and search the list by name.
An implementation of the Visualforce controller and page code for the Angular-powered project list can be found in Listings 7.19 and 7.20. The subsections that follow provide a code walk-through of the Angular-specific aspects of Listing 7.20.
public with sharing class MyPageController7_20 {
@RemoteAction
public static List<Project__c> load() {
return [SELECT Name, Location__c, CreatedDate
FROM Project__c ];
}
}
<apex:page controller="MyPageController7_20">
<style>
.toolbar { margin-bottom: 20px; }
td { padding: 5px; }
</style>
<script>
function ProjectListCtrl($scope, $rootScope) {
MyPageController7_20.load(function(result, event) {
if (event.status) {
$scope.projects = result;
$rootScope.$apply();
}
}, { escape: false });
$scope.orderProp = 'CreatedDate';
}
</script>
<apex:pageBlock tabStyle="Project__c" title="Projects">
<apex:outputPanel html-ng-app=""
html-ng-controller="ProjectListCtrl">
<div class="toolbar">
Search: <input ng-model="query" />
Sort by:
<select ng-model="orderProp">
<option value="Name">Alphabetical</option>
<option value="CreatedDate">Newest</option>
</select>
</div>
<table>
<tr ng-repeat="project in projects
| filter:query | orderBy:orderProp">
<td>
<apex:outputText value="{{project.Name}}" />
</td>
<td>
<apex:outputText value="{{project.Location__c}}" />
</td>
<td>
<apex:outputText value="{{project.CreatedDate
| date}}" />
</td>
</tr>
</table>
</apex:outputPanel>
</apex:pageBlock>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js">
</script>
</apex:page>
The Angular controller is responsible for the business logic of a single view. In Listing 7.20, the Angular controller is named ProjectListCtrl
and specified in an in-line script
tag. It invokes the remote action load
on the Visualforce controller with the option escape: false
. This instructs it to forgo HTML entity encoding of the remote action’s response. When the remote action is completed, the resulting array of projects is provided to Angular, and all its bound user interface elements are notified using the $apply()
method.
Much like a Visualforce page, an Angular template brings the Angular controller and model together into a rendered Web page. It contains HTML, CSS, and Angular-specific markup.
Listing 7.20 contains a single Angular template within a Visualforce outputPanel
component. Important aspects of the template are described in the following list:
The outputPanel
contains custom HTML attributes (prefaced with html-
to make them acceptable to Visualforce) to specify the Angular controller and ng
-app
to register the DOM with Angular. In Visualforce, this sort of control over the HTML output is only possible in an outputPanel
.
The two HTML input fields are bound to the controller using the ng
-model
attribute.
The table row is repeated for each element in the projects
model, filtered by the input query and ordered by the drop-down selection.
Markup (in double curly brace notation) is used to output elements of the model within outputText
components.
A standard HTML script tag includes version 1.0.7 of Angular from Google. This could just as well be loaded from a Force.com static resource or a Visualforce component with the script in-line.
18.189.189.67