A bit of context
Greater Wellington Regional Council oversees flood protection, land management, provision of regional parks, planning and funding of public transport; and one of the services they offered was data aggregation of environmental monitoring stations around the country—served through the Environmental Monitoring app also known as Envmon.
Envmon was originally developed with SilverStripe, and as part of the upgrade process that the project was undergoing, a number of components including the graphing library (Highcharts - highcharts.com) were introduced to replace the previous generated bitmaps. In addition, monitoring of site filtering was integrated with Google Maps.
As the initial proof of concept, more and more features, naturally, started evolving. Then it got out of control as our initially light script got more and more complex … So after a few months down the track, we decided to have a code freeze and to refactor everything and ideally use a framework.
Choosing the right framework
To make the choice, I considered the following: see what’s trending, read comparison and reviews between popular frameworks, and see if there are already team capabilities, etc.
So the objectives for the project were to: build on a solid framework that would easily be scaled up, easily understood and maintained by future developers, super-lean yet super-fast to process heavy data requests; and last but not least, easily integrate with SilverStripe. Following a bit of R&D, it was easy to decide on AngularJS.
Things to note about our setup
We were using: Windows Server 2008, SilverStripe 3.1, Angular 1.5, RequireJS for module loading, Bower for front-end dependency management, Highcharts plugin, Google Maps and lastly we integrated with data aggregation service (Hilltop), which aggregated monitoring data and served it via restful service.
Demo Site
For those wanting to experiment with AngularJS and SilverStripe, we have set up a very basic demo site that integrates the two great technologies. Check out the repo—references to files in the repo will be made throughout the blog.
Theme
~ / themes / simple / …
The following theme setup looks something like this:
-- bower_components
-- css
-- Images
-- javascript
-- Templates
-- webfonts
App JS structure
~ / themes / simple / javascript / ...
-- app
-- app.js
-- controllers.js
-- directives.js
-- filters.js
-- lib.js
-- models.js
-- services.js
-- common.js
-- script.js
Configure RequireJS
~ / themes / simple / javascript / common.js
requirejs.config({
baseUrl: '/themes/simple/javascript/app',
paths: {
// Angular App
app: 'app',
appServices: 'services',
appControllers: 'controllers',
appModels: 'models',
appDirectives: 'directives',
appFilters: 'filters',
// Bower components
angular: '/themes/simple/bower_components/angular/angular',
angularResource: '/themes/simple/bower_components/angular-resource/angular-resource.min',
jquery: '/themes/simple/bower_components/jquery/dist/jquery.min'
},
shim: {
app: {
deps: ['angular', 'appServices', 'appControllers', 'appModels', 'appDirectives', 'appFilters']
},
angular: {
exports: 'angular'
},
angularResource: {
deps: ['angular']
}
}
});
require(['app'], function() {
angular.bootstrap(document, ['app']);
});
Load App
~ / themes / simple / templates / Layout / Page.ss
<script src="/$ThemeDir/bower_components/requirejs/require.js"></script>
<script>
requirejs(['$ThemeDir/javascript/common.js'], function (common) {
requirejs([$ThemeDir/javascript/common.js']);
});
</script>
Fetch data internally
~ / themes / simple / javascript / app / services.js
define ('appServices', ['angular'], function(angular) {
var appServices = angular.module('app.services', []);
appServices.factory('AJAXService', function($http) {
return {
getLocalData: function() {
return $http.get('home/getTestData').then(function(result) {
return result.data;
});
}
}
});
});
Fetch data from restful service
~ / themes / simple / javascript / app / services.js
define('appServices', ['angular'], function(angular) {
var appServices = angular.module('app.services', []);
appServices.factory('AJAXService', function($http) {
return {
...
getCrossDomainData: function() {
return $http.get('http://hilltop.gw.govt.nz/Data.hts?Service=Hilltop&Request=CollectionList').then(function(result) {
return result.data;
});
}
}
});
});
Fetch data from another SilverStripe restfulserver API
Check out SilverStripe RestfulServer Module: https://github.com/silverstripe/silverstripe-restfulserver
GET /api/v1/(ClassName)/(ID)
Gets a database record
GET /api/v1/(ClassName)/(ID)/(Relation)
Get all of the records linked to this database record by the given reatlion
GET /api/v1/(ClassName)?(Field)=(Val)&(Field)=(Val)
searches for matching database records
POST /api/v1/(ClassName)
create a new database record
PUT /api/v1/(ClassName)/(ID)
updates a database record
PUT /api/v1/(ClassName)/(ID)/(Relation)
updates a relation, replacing the existing record(s) (NOT IMPLEMENTED YET)
What I loved about AngularJS
- Takes care of data binding
- Decoupling from the DOM
- $scope
- Enforces better coding standards
- Better cross-browser support
Annoyances
If you’re new to Angular, then be prepared to learn about the new syntax! Once you get over the bump, you’ll love it.
Post your comment
Comments
Posted by Piccosoft, 17/04/2018 12:50am (7 years ago)
Posted by spurtcommerce, 02/03/2018 1:09am (7 years ago)
No one has commented on this page yet.
RSS feed for comments on this page | RSS feed for all comments