angularjs in large applications - ae nv
TRANSCRIPT
ae nv/sa
Interleuvenlaan 27b, B-3001 Heverlee
T +32 16 39 30 60 - F +32 16 39 30 70
www.ae.be
AngularJS in large applications
AngularJS Meetup
2
Agenda
Introduction
Managing a large application
Communication through hypermedia
Break
Reusable components
3
http://www.slideshare.net/AE_nv/angular-js-in-large-applicationshttp://ow.ly/sPVGy
#ajsugbe
4
Introduction
Glenn Dejaeger @glenndejaeger
Experience: 2+ years
Thomas Anciaux @thomaux
Experience: 2+ years
Pieter Herroelen @piether
Experience: 1 year
We work for AE @AE_NV
5
Project context
Enterprise environment
Master database system
CRUD
Spearhead
Internal project
Infrequent releases
6
Project size
17 developers, 4 js developers
10k MD total
LOC’s
JavaScript: 7k
Java REST layer: 11k
Java total: 700k+
11
New Issues
MODULESAPP FRAMEWORK
FRAMEWORKBOOTSTRAP
ANGULAR
ANGULARFRAMEWORK
ANGULAR
BOOTSTRAPMODULES
12
New issues
<base href=“whatever/buildnr/”>
directive(“aDirective”, function(){
return {
...,
templateUrl: “relative/path/...”
...
}
});
14
Dependency Management?
Manual!
Error prone
Not feasible with a large set of dependencies
Wrap dependencies with output
Ugly!
16
Bower
Setup each project as a Bower module
Publish versions independently
Bower can target local or zipped folders
Store the tagged versions anywhere you’d like
17
$templateCache
Angular service
Registers templates by name
Grunt task compiles and concatenates all HTML to JS
18
Conclusion
Advantages
Automation of build system
Closer to pure angular (easy Karma setup etc.)
Dependency management
Disadvantages
One big file per project/module
Harder to use Chrome Dev tools
21
Project needs
A lot of similar functionality (CRUD)
Hierarchical data
Flexible UI: “A browser in a browser”
Multiple tabs
Links all over the place
...
22
First approach
"municipality": {
"criteria": {
"groups": [["LABEL“,"POSTAL_CODE"]],
“label": {
"type": "TEXT_MEDIUM",
"operators": "ALPHA",
"common": true,
"mandatory": false
},
…
},
…
24
First approach
http://www.youtube.com/watch?v=62RvRQuMVyg
25
Richardson maturity model
http://martinfowler.com/articles/richardsonMaturityModel.html
27
Richardson maturity model
http://martinfowler.com/articles/richardsonMaturityModel.html
30
http://www.toddmgreen.com/wp-content/uploads/2011/12/Arthur-C-2.png
36
HAL - Hypertext Application Language
http://stateless.co/hal_specification.html
38
"_links": {
"self": { "href": "/orders"}
},
"currentlyProcessing": 14,
"shippedToday": 20,
"_embedded": {
"ea:order": [
{
"_links": {
"self": { "href": "/orders/123" },
"ea:basket": { "href": "/baskets/98712" }
},
"total": 30.00
}
...
39
"_links": {
"self": { "href": "/orders"}
},
"currentlyProcessing": 14,
"shippedToday": 20,
"_embedded": {
"ea:order": [
{
"_links": {
"self": { "href": "/orders/123" },
"ea:basket": { "href": "/baskets/98712" }
},
"total": 30.00
}
...
40
"_links": {
"self": { "href": "/orders"}
},
"currentlyProcessing": 14,
"shippedToday": 20,
"_embedded": {
"ea:order": [
{
"_links": {
"self": { "href": "/orders/123" },
"ea:basket": { "href": "/baskets/98712" }
},
"total": 30.00
}
...
44
follow() Replace content of directive with resource behind link
Example:<a ng-click=“links[‘children’].follow()”></a>
45
function(method, data) Do an HTTP call with the specified method and the specified data in the request. Returns a promise.
Example:
$scope.links[‘save’](‘POST’, $scope.form).then(...);
50
JSON $scope
• properties• links• embedded
property• header
HTML
<ng-include
src=“property+’.html’”>
</ng-include>
59
What is a component?
An identifiable part of a larger program or construction
Provides a particular function or group of related functions
Has its own responsibility
62
Grid component
directive(“grid”, function(){
return {
...
scope: {
data: ‘=‘,
columnDefs: ‘=‘,
sortable: ‘=‘,
filterable: ‘=‘
...
}
controller: ‘gridController’,
template: $templateCache.get(‘grid.html')
...
}
});
63
Grid component
<div ng-init=“columnDefs=[
{field: ‘firstName’, title: ’firstname’},
{field: ‘lastName’, title: ’lastname’},
{field: ‘city’, title: ’city’},
{field: ‘title’, title: ’title’},
{field: ‘birthDate’, title:’birthdate’},
{field: ‘age’, title:’age’},
]”>
<div grid
data=“$scope.persons”
column-defs=“columnDefs”></div>
</div>
65
Solution
Different services with their own responsibility
Injected into controller
Only logic, no state!
67
Solution
<div grid data=“$scope.persons”>
<div grid-column field=“firstName” title=“firstname”/>
<div grid-column field=“lastName” title=“lastname”/>
<div grid-column field=“city” title=“city”/>
<div grid-column field=“title” title=“title”/>
<div grid-column field=“birthDate” title=“birthdate”/>
<div grid-column field=“age” title=“age”/>
</div>
70
Grid component
directive(“gridColumn”, function(){
return {
...
scope: {
field: ‘@‘,
title: ‘@‘,
hidden: ‘=‘
...
}
require: ‘^grid’,
link: function(scope, elem, attrs, gridCtrl){
...
}
...
});
71
Communication between components
Isolated scopes
Don’t pollute other scopes
No direct access to parent scope
72
Communication between components
Events
Loosely coupled
No control over listeners
Shared services
Tightly coupled
Control over consumers
73
Parting words
Solved a number of problems
Modularity of the build
Interaction with a hypermedia back-end
Modularity of the code
Created a few new problems
YMMV
@ae_nv
linkedin.com/company/ae-nv-sa