Top Banner
AngularJS: Good parts Евгений Жарков DOOR3 @2j2e [email protected]
35

AngularJS: Good parts

Apr 12, 2017

Download

Technology

Eugene Zharkov
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: AngularJS: Good parts

AngularJS: Good parts

Евгений Жарков DOOR3

@2j2e [email protected]

Page 2: AngularJS: Good parts

Watchers ]:>

Page 3: AngularJS: Good parts

Track Watchers

Angular adds a watcher to the digest cycle for each of these:• {{expression}} — templates• $scope.$watch — in the code

Page 4: AngularJS: Good parts

Track WatchersfunctiongetWatchers(root){root=angular.element(root||document.documentElement);varwatcherCount=0;functiongetElemWatchers(element){varisolateWatchers=getWatchersFromScope(element.data().$isolateScope);varscopeWatchers=getWatchersFromScope(element.data().$scope);varwatchers=scopeWatchers.concat(isolateWatchers);angular.forEach(element.children(),function(childElement){watchers=watchers.concat(getElemWatchers(angular.element(childElement)));});returnwatchers;}functiongetWatchersFromScope(scope){if(scope){returnscope.$$watchers||[];}else{return[];}}returngetElemWatchers(root);}

https://gist.github.com/kentcdodds/31c90402750572107922

Page 5: AngularJS: Good parts

Track Watchers

//getallwatchersonthewholepagegetWatchers();//getwatchersofaspecificelement(anditschildren)getWatchers(document.body);//selecttheelementofinterestinChromeDevtoolsgetWatchers($0);

Page 6: AngularJS: Good parts
Page 7: AngularJS: Good parts

Track Watchers

Page 8: AngularJS: Good parts
Page 9: AngularJS: Good parts
Page 10: AngularJS: Good parts
Page 11: AngularJS: Good parts

https://github.com/kentcdodds/ng-stats

Page 12: AngularJS: Good parts

AngularJS > ES6

Page 13: AngularJS: Good parts

ES6, require.js

functionMainController(){……………}

export{MainController}

—————————————————————————————————————

import{MainController}from‘./path/to/MainController';……………

Page 14: AngularJS: Good parts

ES6, require.jsclassMainController{

constructor(searchService){this.searchService=searchService;}

search(){this.searchService.fetch(this.searchTerm).then(response=>{this.items=response.data.items;});}}

export{MainController}

Page 15: AngularJS: Good parts

ES6, require.js

import{MainController}from'./MainController';

import{SearchService}from'./SearchService';

angular

.module('app',[])

.controller('mainController',MainController)

.service('searchService',SearchService);

Page 16: AngularJS: Good parts

Inheritance

classPageController{

constructor(title){

this._title=title;}

title(){

return'Title:'+this._title;}}

export{PageController}

Page 17: AngularJS: Good parts

Inheritance

import{PageController}from'./PageController';

classProductPageControllerextendsPageController{

constructor(){

super('ES6inheritancewithAngular’);

}}

export{ProductPageController}

Page 18: AngularJS: Good parts

Inheritance

import{ProductPageController}from'./ProductPageController';

angular

.module('app',[])

.controller('ProductPageController',ProductPageController);

Page 19: AngularJS: Good parts

Service Inheritance

myModule.service(fn)

YES, instantiated with the new operator under the hood

myModule.factory(fn)

NO

Page 20: AngularJS: Good parts

Don’t forget about minification

MainController.$inject=['SearchService'];

Page 21: AngularJS: Good parts

and/or ng-annotate

exportdefaultclassNameService{

/*@ngInject*/

constructor($q){..}

}

Page 22: AngularJS: Good parts

ES6 Babel Browserify Boilerplate

https://github.com/thoughtram/es6-babel-browserify-boilerplate

Page 23: AngularJS: Good parts

Angular ES6

https://github.com/michaelbromley/angular-es6

Page 24: AngularJS: Good parts

AngularJS > ES6 > Tests

Page 25: AngularJS: Good parts

ES5, Karma, Jasmine, PhantomJSdescribe('TodoService',function(){

varTodoService,InitialTodosMock;//InstantiateAngularJScontextbeforeEach(module("app"));//RegistermocksinAngularJScontextbeforeEach(module(function($provide){InitialTodosMock=[{label:'Testtodo',done:false}];$provide.value('initialTodos',InitialTodosMock);}));//GetinstanceofTodoServicewithmockeddependenciesfromAngularJScontextbeforeEach(inject(function(_TodoService_){TodoService=_TodoService_;}));//Oh,...dotheactualtesting!!!it('shouldhaveinitialtodo',function(){expect(TodoService.todos.length).toBe(1);expect(TodoService.todos[0].label]).toBe('Testtodo');expect(TodoService.todos[0].done]).toBe(false);

});});

Page 26: AngularJS: Good parts

ES5, Karma, Jasmine, PhantomJSdescribe('TodoController',function(){varscope,$rootScope,$controller;//InstantiateAngularJScontextbeforeEach(module('app'));//RegistermocksinAngularJScontext//(sometimesnotnecessary,wecanuserealservicestoo,buttheAngularcontextgrows...)beforeEach(module(function($provide){varTodoServiceMock={todos:[],addTodo:function(){/*……*/},toggleTodo:function(){/*……*/},removeDoneTodost(){/*……*/}};$provide.value('TodoService',TodoServiceMock);}));//GetinstanceofTodoController,youknow,createnew$scopefrom$rootScopebyyourselfandstuff...//Itispossibletonotuse$scopewhenusing'controllerAs'syntax,//butyoustillhavetouseatleast$controllertogettherefferencetocontrolleritselfbeforeEach(inject(function(_$rootScope_,_$controller_,_TodoService_){$controller=_$controller_;$rootScope=_$rootScope_;scope=$rootScope.$new();

$controller('TodoController',{$scope:scopeTodoService:_TodoService_});}));//Oh,...dotheactualtesting!!!it('shouldhaveinitialtodos',function(){expect(scope.todos.length).toBe(1);});});

Page 27: AngularJS: Good parts

Issues

• Angular context module(‘app’) must be instantiated to be able to do any testing. Without Angular context you can’t get access (reference) to your controllers / services.

• Angular and all other used libraries must be included during testing so that it is even possible to instantiate Angular context.

• Angular context can grow quite large so that it’s creation will consume considerable amount of time for every test file.

• Karma exclusion syntax doesn’t follow standard node glob pattern which can make you go crazy when you try to solve timeout errors caused by insufficient memory on PhantomJS by splitting test execution into multiple batches, while supporting dev mode single test execution (karma uses extra exclude property instead of supporting standard “!”)

Page 28: AngularJS: Good parts

ES6, Mocha, chaiimport{assert}from'chai';importTodoServicefrom'./todo.service.js';

letservice;

describe('TodoService',function(){beforeEach(function(){service=TodoService();});

it('shouldcontainemptytodosafterinitialization',function(){assert.equal(service.todos.length,0);});

it('shouldtoggletodo',function(){service.addTodo('Finishexampleproject');assert.equal(service.todos[0].done,false);service.toggleTodo('Finishexampleproject');assert.equal(service.todos[0].done,true);service.toggleTodo('Finishexampleproject');assert.equal(service.todos[0].done,false);});});

Page 29: AngularJS: Good parts

ES6, Mocha, chaiimport{assert}from'chai';importSomeComponentfrom‘./some-component';

letcomponent;

describe('some-component',function(){beforeEach(function(){component=newSomeComponent();});

it('shouldstartwithcountervalue20',function(){assert.equal(component.counter,20);});

it('shouldacceptinitialcountervalueasdependency',function(){component=newSomeComponent(30);assert.equal(component.counter,30);});

it('shouldincrementcountervalueafterincrementiscalled',function(){assert.equal(component.counter,20);component.increment();assert.equal(component.counter,21);});});

Dependencies are passed explicitly as a parameter of function

Page 30: AngularJS: Good parts

Dig, read, criticise

• Paginationhttps://github.com/michaelbromley/angularUtils/tree/master/src/directives/pagination

• angular-formly http://angular-formly.com/

• angular-translatehttps://angular-translate.github.io

• LumX (material design) http://ui.lumapps.com

Page 31: AngularJS: Good parts

angular-formly

<formly-formmodel="vm.user"fields="vm.userFields">

<buttontype="submit"class="btnbtn-default"ng-click="vm.submit(vm.user)">Submit</button>

</formly-form>

Page 32: AngularJS: Good parts

angular-formlyvm.userFields=[{key:'email',type:'input',templateOptions:{type:'email',label:'Emailaddress',placeholder:'Enteremail'}},{key:'password',type:'input',templateOptions:{type:'password',label:'Password',placeholder:'Password'}},

{key:'file',type:'file',templateOptions:{label:'Fileinput',description:'Exampleblock-levelhelptexthere',url:'https://example.com/upload'}},{key:'checked',type:'checkbox',templateOptions:{label:'Checkmeout'}}];

Page 33: AngularJS: Good parts

Pagination

<ANY

dir-paginate="expression|itemsPerPage:(int|expression)[:paginationId(stringliteral)]"

[current-page=""]

[pagination-id=""]

[total-items=""]>

...

</ANY>

Page 34: AngularJS: Good parts

Pagination

<dir-pagination-controls

[max-size=""]

[direction-links=""]

[boundary-links=""]

[on-page-change=""]

[pagination-id=""]

[template-url=""]

[auto-hide=""]>

</dir-pagination-controls>

Page 35: AngularJS: Good parts