angularjs in practice

60
©2014 Dealertrack, Inc. All rights reserved. Jon Hoguet Sr. UI Developer [email protected] AngularJS in Practice

Upload: jhoguet

Post on 19-Jun-2015

265 views

Category:

Software


3 download

DESCRIPTION

Already seen the angular basics? Ready for a deeper dive? Lets dive into how angular is being used at Dealer.com and dive deep into $compile and what those magic directive symbols really mean. If you didn't make it to VT Code Camp to see this in person, then you should read this post which is the basis for the slides. http://goo.gl/JMf0ss

TRANSCRIPT

Page 1: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Jon HoguetSr. UI [email protected]

AngularJS in Practice

Page 2: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Jon Hoguet who?

Page 3: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

▪ Our Architecture▪ Overview▪ Metrics▪ File Structure▪ Lessons Learned

▪ Angular ▪ Controller▪ Directive▪ $compile▪ Directives and Isolate Scope▪ Lessons Learned

▪ Build▪ Grunt▪ Testing with Karma▪ Testing with Protractor

▪ Debugging▪ $log▪ in the browser

▪ I reading this online, you should check out the ▪ Correlating Blog Post

What to expect

Page 4: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Our Architecture

Page 5: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

15 Angular Modules

43 Angular Directives

15 Angular Controllers

36 Angular Services

52 Angular Templates

13,669 lines of javascript

Focusing on Angular

Page 6: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Some Humility

Page 7: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

File Structure

Page 8: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Minimal Grails dependency

Page 9: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Do organize around functionality

Build First

Don’t mix templating languages

Lessons Learned

Page 10: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Don’t mix templating languages

<inventory:firedoor firedoorClass="search-firedoor lifecycle-criteria"

ngshow="lifecycles.targetLifecycle.isEditingCriteria" fluid="false"

customButtons="${[ [click:

'lifecycles.targetLifecycle.isEditingCriteria=false', icon: 'check', text: 'Done', customClass:

'btn-primary'] ]}">

<div class="form-group lifecycle-name-group">

<input type="text" class="form-control input-lg"

ng-model="lifecycles.targetLifecycle.model.name"

ng-change="lifecycles.targetLifecycle.dirty()"

placeholder="Enter a name...">

</div><div criteria-form title="Lifecycle Criteria"

criteria-model="lifecycles.targetLifecycle.model.criteria"

dirty="lifecycles.targetLifecycle.dirty">

</div>

</inventory:firedoor>

Page 11: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Controllers vs Directives

Page 12: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

A controller is an abstraction of

a directive

Page 13: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Consider...

Page 14: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Controller right?

Page 15: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Somewhere else in the dom...

Page 16: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Controller abstraction of directive isn’t working… use a directive

Page 17: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Page 18: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

$compile = BFF

$compile( markup / directives )( scope ) = live dom

fragment

1. Most important thing angular does2. composable3. makes testing easy4. makes experimentation easy

Page 19: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

live dom element

var ioc = angular.element('[ng-app]').injector(),

$rootScope = ioc.get('$rootScope'),

$compile = ioc.get('$compile');

var scope = $rootScope.$new(true);

scope.child = {

name : 'Lance',

age : 3

};

var markup = "<div>{{ child.name }} is {{ child.age }} years old!</div>";

var el;

scope.$apply(function(){

el = $compile(markup)(scope);

});

// el.html() === 'Lance is 3 years old!'

Page 20: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

live dom element

var ioc = angular.element('[ng-app]').injector(),

$rootScope = ioc.get('$rootScope'),

$compile = ioc.get('$compile');

var scope = $rootScope.$new(true);

scope.child = {

name : 'Lance',

age : 3

};

var markup = "<div>{{ child.name }} is {{ child.age }} years old!</div>";

var el;

scope.$apply(function(){

el = $compile(markup)(scope);

});

// el.html() === 'Lance is 3 years old!'

Page 21: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

live dom element

var ioc = angular.element('[ng-app]').injector(),

$rootScope = ioc.get('$rootScope'),

$compile = ioc.get('$compile');

var scope = $rootScope.$new(true);

scope.child = {

name : 'Lance',

age : 3

};

var markup = "<div>{{ child.name }} is {{ child.age }} years old!</div>";

var el;

scope.$apply(function(){

el = $compile(markup)(scope);

});

// el.html() === 'Lance is 3 years old!'

Page 22: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

live dom element

var ioc = angular.element('[ng-app]').injector(),

$rootScope = ioc.get('$rootScope'),

$compile = ioc.get('$compile');

var scope = $rootScope.$new(true);

scope.child = {

name : 'Lance',

age : 3

};

var markup = "<div>{{ child.name }} is {{ child.age }} years old!</div>";

var el;

scope.$apply(function(){

el = $compile(markup)(scope);

});

// el.html() === 'Lance is 3 years old!'

Page 23: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

live dom element

var ioc = angular.element('[ng-app]').injector(),

$rootScope = ioc.get('$rootScope'),

$compile = ioc.get('$compile');

var scope = $rootScope.$new(true);

scope.child = {

name : 'Lance',

age : 3

};

var markup = "<div>{{ child.name }} is {{ child.age }} years old!</div>";

var el;

scope.$apply(function(){

el = $compile(markup)(scope);

});

// el.html() === 'Lance is 3 years old!'

Page 24: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

live dom element

var ioc = angular.element('[ng-app]').injector(),

$rootScope = ioc.get('$rootScope'),

$compile = ioc.get('$compile');

var scope = $rootScope.$new(true);

scope.child = {

name : 'Lance',

age : 3

};

var markup = "<div>{{ child.name }} is {{ child.age }} years old!</div>";

var el;

scope.$apply(function(){

el = $compile(markup)(scope);

});

// el.html() === 'Lance is 3 years old!'

Page 25: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

What do you mean live?

scope.$apply(function(){

scope.child = {

name : 'Lana',

age : 2

};

});

//el.html() === 'Lana is 2 years old!'

Page 26: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Live meaning 2 way

markup = "<input type=\"text\" ng-model=\"child.name\" />";

var input;

// note we are applying the same scope to this markup

scope.$apply(function(){

input = $compile(markup)(scope);

});

input.val('Lana Hoguet');

input.change();

// scope.name === 'Lana Hoguet'

// el.html() === 'Lana Hoguet is 2 years old!'

Page 27: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Live meaning 2 way

markup = "<input type=\"text\" ng-model=\"child.name\" />";

var input;

// note we are applying the same scope to this markup

scope.$apply(function(){

input = $compile(markup)(scope);

});

input.val('Lana Hoguet');

input.change();

// scope.name === 'Lana Hoguet'

// el.html() === 'Lana Hoguet is 2 years old!'

Page 28: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Live meaning 2 way

markup = "<input type=\"text\" ng-model=\"child.name\" />";

var input;

// note we are applying the same scope to this markup

scope.$apply(function(){

input = $compile(markup)(scope);

});

input.val('Lana Hoguet');

input.change();

// scope.child.name === 'Lana Hoguet'

// el.html() === 'Lana Hoguet is 2 years old!'

Page 29: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Live meaning 2 way

markup = "<input type=\"text\" ng-model=\"child.name\" />";

var input;

// note we are applying the same scope to this markup

scope.$apply(function(){

input = $compile(markup)(scope);

});

input.val('Lana Hoguet');

input.change();

// scope.child.name === 'Lana Hoguet'

// el.html() === 'Lana Hoguet is 2 years old!'

Page 30: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Hurt yet?

Page 31: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Directives Refresher

Page 32: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Directives Refresher

= for two way

@ for one way

& for functions

Page 33: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

one way / two way misnomer

Page 34: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

one way / two way misnomer$compile source code

Page 35: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

one way / two way misnomer$compile source code

Page 36: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

one way / two way misnomer

Note: $interpolate and $parse are not coupled to $scope

Page 37: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

= for two way uses $parse

@ for one way uses $interpolate

& for functions

Page 38: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

& demystified

Page 39: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

& demystified

$compile source code

Page 40: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

= for two way uses $parse

@ for one way uses $interpolate

& for functions wraps $parse in fn

Page 41: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

= for two way uses $parse and watches

@ for one way uses $interpolate and watches

& for functions wraps $parse in fn

Page 42: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Page 43: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Beware the ng-model monster

fiddle

Page 44: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Page 45: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Page 46: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

angular-templates

Not proposing you use inline scripts - just simple example

Page 47: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

angular-templates

$templateCache

$http

Not proposing you use inline scripts - just simple example

Page 48: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

angular-templates

ng-include, ng-view, ui-view, or templateUrl

$http $templateCache

Page 49: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

angular-templates

npm install grunt-angular-templates --save-dev

Page 50: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

angular-templates

Page 51: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

angular-modules

Page 52: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

angular-modules

Page 53: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Page 54: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Unit testing directives is easy!

Page 55: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Protractor

Not Just for Angular

But has angular specific hooks built in

Promises!!

Page 56: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Debugging - Log More

Page 57: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Debugging - In the Browser

You can get anything out of IOC

Page 58: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Debugging - In the Browser

You can inspect any scope

Page 59: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Debugging - In the Browser

You can mutate the scope and verify how the view reacts

Page 60: AngularJS in practice

©2014 Dealertrack, Inc. All rights reserved.

Conclusion