Recently i authored a visualforce page just to demonstrate the use of angular JS (Javascript framework from google ).It was very good experience working with Harshit Pandey.
The idea was just to demonstrate how easily even with getters concept of visualforce one can bind data to the angular JS script
The page gives functionality of sorting ,pagination and searching all in a single UI.The UI is done through twitter bootstrap plugin.
The page code can be found below
The idea was just to demonstrate how easily even with getters concept of visualforce one can bind data to the angular JS script
The page gives functionality of sorting ,pagination and searching all in a single UI.The UI is done through twitter bootstrap plugin.
The page code can be found below
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<apex:page standardStylesheets="false" sidebar="false" showHeader="false" controller="AngularJSDemoCtrl"> | |
<html xmlns:ng="http://angularjs.org" ng-app="hello" lang="en"> | |
<head> | |
<meta charset="utf-8"/> | |
<link href="https://netdna.bootstrapcdn.com/twitter-bootstrap/2.1.1/css/bootstrap.no-icons.min.css" rel="stylesheet"/> | |
<link href="https://netdna.bootstrapcdn.com/font-awesome/2.0/css/font-awesome.css" rel="stylesheet"/> | |
<apex:includeScript value="{!$Resource.Angularjs}"/> | |
</head> | |
<script type="text/javascript"> | |
var sortingOrder = 'name'; | |
</script> | |
<script type="text/javascript"> | |
var myapp = angular.module('hello', []); | |
var contrl=myapp.controller('ctrlRead', function ($scope, $filter) { | |
// init | |
$scope.sortingOrder = sortingOrder; | |
$scope.reverse = false; | |
$scope.filteredItems = []; | |
$scope.groupedItems = []; | |
$scope.itemsPerPage = 15; | |
$scope.pagedItems = []; | |
$scope.currentPage = 0; | |
$scope.items ={!lstAccount}; | |
// alert(JSON.stringify($scope.items)); | |
var searchMatch = function (haystack, needle) { | |
if (!needle) { | |
return true; | |
} | |
return haystack.toLowerCase().indexOf(needle.toLowerCase()) !== -1; | |
}; | |
// init the filtered items | |
$scope.search = function () { | |
$scope.filteredItems = $filter('filter')($scope.items, function (item) { | |
for (var attr in item) { | |
if (searchMatch(item[attr], $scope.query)) | |
return true; | |
} | |
return false; | |
}); | |
// take care of the sorting order | |
if ($scope.sortingOrder !== '') { | |
$scope.filteredItems = $filter('orderBy')($scope.filteredItems, $scope.sortingOrder, $scope.reverse); | |
} | |
$scope.currentPage = 0; | |
// now group by pages | |
$scope.groupToPages(); | |
}; | |
// calculate page in place | |
$scope.groupToPages = function () { | |
$scope.pagedItems = []; | |
for (var i = 0; i < $scope.filteredItems.length; i++) { | |
if (i % $scope.itemsPerPage === 0) { | |
$scope.pagedItems[Math.floor(i / $scope.itemsPerPage)] = [$scope.filteredItems[i]]; | |
} else { | |
$scope.pagedItems[Math.floor(i / $scope.itemsPerPage)].push($scope.filteredItems[i]); | |
} | |
} | |
}; | |
$scope.range = function (start, end) { | |
var ret = []; | |
if (!end) { | |
end = start; | |
start = 0; | |
} | |
for (var i = start; i < end; i++) { | |
ret.push(i); | |
} | |
return ret; | |
}; | |
$scope.prevPage = function () { | |
if ($scope.currentPage > 0) { | |
$scope.currentPage--; | |
} | |
}; | |
$scope.nextPage = function () { | |
if ($scope.currentPage < $scope.pagedItems.length - 1) { | |
$scope.currentPage++; | |
} | |
}; | |
$scope.setPage = function () { | |
$scope.currentPage = this.n; | |
}; | |
// functions have been describe process the data for display | |
$scope.search(); | |
// change sorting order | |
$scope.sort_by = function (newSortingOrder) { | |
if ($scope.sortingOrder == newSortingOrder) | |
$scope.reverse = !$scope.reverse; | |
$scope.sortingOrder = newSortingOrder; | |
// icon setup | |
$('th i').each(function () { | |
// icon reset | |
$(this).removeClass().addClass('icon-sort'); | |
}); | |
if ($scope.reverse) | |
$('th.' + new_sorting_order + ' i').removeClass().addClass('icon-chevron-up'); | |
else | |
$('th.' + new_sorting_order + ' i').removeClass().addClass('icon-chevron-down'); | |
}; | |
}); | |
contrl.$inject = ['$scope', '$filter']; | |
</script> | |
<body> | |
<div ng-controller="ctrlRead"> | |
<div class="input-append"> | |
<input type="text" ng-model="query" ng-change="search()" class="input-large search-query" placeholder="Search"/> | |
<span class="add-on"><i class="icon-search"></i></span> | |
</div> | |
<table class="table table-striped table-condensed table-hover"> | |
<thead> | |
<tr> | |
<th class="id">Id <a ng-click="sort_by('id')"><i class="icon-sort"></i></a></th> | |
<th class="name">Name <a ng-click="sort_by('name')"><i class="icon-sort"></i></a></th> | |
<th class="Website">Website <a ng-click="sort_by('Website')"><i class="icon-sort"></i></a></th> | |
<th class="AccountSource">AccountSource <a ng-click="sort_by('AccountSource')"><i class="icon-sort"></i></a></th> | |
<th class="Phone">Phone <a ng-click="sort_by('Phone')"><i class="icon-sort"></i></a></th> | |
<th class="Type">Type <a ng-click="sort_by('Type')"><i class="icon-sort"></i></a></th> | |
</tr> | |
</thead> | |
<tfoot> | |
<td colspan="6"> | |
<div class="pagination pull-right"> | |
<ul> | |
<li ng-class="{disabled: currentPage == 0}"> | |
<a ng-click="prevPage()">« Prev</a> | |
</li> | |
<li ng-repeat="n in range(pagedItems.length)" | |
ng-class="{active: n == currentPage}" | |
ng-click="setPage()"> | |
<a ng-bind="n + 1">1</a> | |
</li> | |
<li ng-class="{disabled: currentPage == pagedItems.length - 1}"> | |
<a ng-click="nextPage()">Next »</a> | |
</li> | |
</ul> | |
</div> | |
</td> | |
</tfoot> | |
<tbody> | |
<tr ng-repeat="item in pagedItems[currentPage] | orderBy:sortingOrder:reverse"> | |
<td>{{item.id}}</td> | |
<td>{{item.name}}</td> | |
<td>{{item.Website}}</td> | |
<td>{{item.AccountSource}}</td> | |
<td>{{item.Phone}}</td> | |
<td>{{item.Type}}</td> | |
</tr> | |
</tbody> | |
</table> | |
</div> | |
</body> | |
</html> | |
</apex:page> |
The controller code is very simple and its just returning JSON object
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
global with sharing class AngularJSDemoCtrl { | |
public class Accountwrap { | |
Accountwrap() { | |
Website = ''; | |
AccountSource = ''; | |
Phone = ''; | |
Type = ''; | |
} | |
public string id; | |
public string name; | |
public string Website; | |
public string AccountSource; | |
public string Phone; | |
public string Type; | |
} | |
global static String getlstAccount() { | |
List < Accountwrap > lstwrap = new List < Accountwrap > (); | |
List < account > lstacc = [SELECT Id, Name, Phone, Type, Website, AccountSource | |
FROM Account | |
]; | |
for (Account a: lstacc) { | |
Accountwrap awrap = new Accountwrap(); | |
awrap.id = a.id; | |
awrap.name = a.name; | |
if (a.Website != null) { | |
awrap.Website = a.Website; | |
} | |
if (a.Phone != null) { | |
awrap.Phone = a.Phone; | |
} | |
if (a.Type != null) { | |
awrap.Type = a.Type; | |
} | |
if (a.AccountSource != null) { | |
awrap.AccountSource = a.AccountSource; | |
} | |
lstwrap.add(awrap); | |
} | |
return JSON.serialize(lstwrap); | |
} | |
} |
The same post is posted by Harshit in a friendly format .You can find at following link http://www.oyecode.com/2013/06/getting-started-with-angularjs-on.html
Thanks and Happy Coding !
Thanks and Happy Coding !