angularjs in large applications - ae nv

75
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

Upload: ae-architects-for-business-and-ict

Post on 20-Aug-2015

3.446 views

Category:

Technology


1 download

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+

7

MANAGING A LARGE APPLICATIONPART 1

8

Historical Issues

MODULESAPP FRAMEWORK

APP.LESS

MODULES.LESS

REQUIREJS

9

Historical issues

No real build

Manual

Monolithic

RequireJS

Karma

10

Initial solutions

Introduce Grunt

And separate builds

Remove dependency on RequireJS

11

New Issues

MODULESAPP FRAMEWORK

FRAMEWORKBOOTSTRAP

ANGULAR

ANGULARFRAMEWORK

ANGULAR

BOOTSTRAPMODULES

12

New issues

<base href=“whatever/buildnr/”>

directive(“aDirective”, function(){

return {

...,

templateUrl: “relative/path/...”

...

}

});

13

New issues

Dependency management?

Referencing HTML templates

14

Dependency Management?

Manual!

Error prone

Not feasible with a large set of dependencies

Wrap dependencies with output

Ugly!

15

New Solution

Introduce Bower

Introduce $templateCache

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

19

QUESTIONS?

20

COMMUNICATION THROUGHHYPERMEDIA

PART 2

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

},

},

23

First approach

CLIENT SERVER

CONFIG

DATA

24

First approach

http://www.youtube.com/watch?v=62RvRQuMVyg

25

Richardson maturity model

http://martinfowler.com/articles/richardsonMaturityModel.html

26

27

Richardson maturity model

http://martinfowler.com/articles/richardsonMaturityModel.html

28

Hypermedia

CLIENT SERVERHYPERMEDIA

29

Hypermedia

CLIENT SERVERJSON over HTTP

30

http://www.toddmgreen.com/wp-content/uploads/2011/12/Arthur-C-2.png

31

Hypermedia

CLIENT SERVERHYPERMEDIA

Content-type: application/hal+json

32

Hypermedia

Content-type: application/hal+json

SPEC

33

Hypermedia

Content-type: application/hal+json

SPEC

CLIENT SERVER

34

Which specification?

35

36

HAL - Hypertext Application Language

http://stateless.co/hal_specification.html

37

HAL

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

}

...

41

EPiaAACBSwaADEtPoHTMD

<resource uri=“http://example.com/path”> ...

42

JSON $scope

• properties• links• embedded

objects

43

JSON $scope

• properties• links• embedded

functions

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(...);

46

HAL

CLIENT SERVER

47

HAL

CLIENT SERVER

LINK RELATIONS

48

JSON $scope

• properties• links• embedded

Recursive structure

49

JSON $scope

• properties• links• embedded

property• header

HTML

50

JSON $scope

• properties• links• embedded

property• header

HTML

<ng-include

src=“property+’.html’”>

</ng-include>

51http://www.x17online.com/gisele-elephant.jpg

52

Where is the model?

53http://www.x17online.com/gisele-elephant.jpg

54

QUESTIONS?

55

BREAKPART 2.5

56

DEVELOPING REUSABLE COMPONENTS

PART 3

57

58

What is a component?

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

60

What is a component?

COMPONENT DIRECTIVE

61

Grid component

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>

64

Problem 1

1 big controller

Unreadable

Unmaintainable

No separation of concerns

65

Solution

Different services with their own responsibility

Injected into controller

Only logic, no state!

66

Problem 2

1 big object to configure all the columns

Unreadable

Static

Error prone

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>

68

What is a component?

COMPONENT DIRECTIVEDIRECTIVE

DIRECTIVE

69

Grid component

directive(“grid”, function(){

return {

...

transclude: true

...

}

});

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

74

QUESTIONS?