Download - Developing Custom Directives by Yuri Takhteyev, CTO at rangle.io

Transcript
Page 1: Developing Custom Directives by Yuri Takhteyev, CTO at rangle.io

Developing CustomDirectives(when to do it and when not to)

Yuri Takhteyev, rangle.iohttp://yto.io@qaramazov

Page 2: Developing Custom Directives by Yuri Takhteyev, CTO at rangle.io

Directives I’ve Knowand Loved

<ion-slide-box on-slide-changed="content.switchSlide(index)"> <ion-slide ng-repeat="item in content.items"> {{item.name}} </ion-slide></ion-slide-box>

But should you do it at home?

Page 3: Developing Custom Directives by Yuri Takhteyev, CTO at rangle.io

Directives vs what?

Page 4: Developing Custom Directives by Yuri Takhteyev, CTO at rangle.io

Skinny controllers& skinny directives

Page 5: Developing Custom Directives by Yuri Takhteyev, CTO at rangle.io

DO NOT$scope.placeOrder = function() { var total = 0; angular.each($scope.items,function(item) { total = item.price * item.quantity * HST; }); $http.post('/api/orders', { chargeAmoung: total }) .success(function(...) { ... }) .catch(function(...) {

});}

Page 6: Developing Custom Directives by Yuri Takhteyev, CTO at rangle.io

DO$scope.placeOrder = function() { // Adjust the UI orders.placeOrder($scope.items) .then(function() { // Adjust the UI }) .then(null, function(error) { // Adjust the UI });}

☛ Same for directives!

Page 7: Developing Custom Directives by Yuri Takhteyev, CTO at rangle.io

Traditional Controllers<div ng-controller="EditorCtrl"> <div ng-controller="DeleteDialogCtrl"> <ul ng-controller="ContentCtrl"> <li ng-repeat="item in items"> {{item.name}} <button ng-click="edit(item)"> Edit </button> <button ng-click="showDeleteDialog(item)"> Delete </button> </li> </ul> </div></div>

Page 8: Developing Custom Directives by Yuri Takhteyev, CTO at rangle.io

“Controller as...”<div ng-controller="EditorCtrl as editor"> <div ng-controller= "DeleteDialogCtrl as deleter"> <ul ng-controller="ContentCtrl as content"> <li ng-repeat="item in content.items"> {{item.name}} <button ng-click="editor.show(item)"> Edit </button> <button ng-click="deleter.show(item)"> Delete </button> </li> </ul> </div>

Page 9: Developing Custom Directives by Yuri Takhteyev, CTO at rangle.io

“Good” controllers vsdirectives

●☛ Multiple use●☛ DOM manipulation *●☛ Degree of isolation

● * If you must...

Page 10: Developing Custom Directives by Yuri Takhteyev, CTO at rangle.io

Reuse

☛ Consider ng-repeat☛ Consider ng-include☛ Consider ui-router

<acme-user username="alice"></acme-user> messaged <acme-user username="bob"></acme-user>

Page 11: Developing Custom Directives by Yuri Takhteyev, CTO at rangle.io

Integrated<div ng-controller="EditorCtrl"> <div ng-controller="DeleteDialogCtrl"> <ul ng-controller="ContentCtrl"> <li ng-repeat="item in items"> {{item.name}} <button ng-click="edit(item)"> Edit </button> <button ng-click="showDeleteDialog(item)"> Delete </button> </li> </ul> </div></div>

Page 12: Developing Custom Directives by Yuri Takhteyev, CTO at rangle.io

Isolated<div ng-controller="EditorCtrl"> <div ng-controller="DeleteDialogCtrl"> <ul ng-controller="ContentCtrl"> <li ng-repeat="item in items" acme-item="{{item}}"></li> </ul> </div></div>

☛ But is it?

Page 13: Developing Custom Directives by Yuri Takhteyev, CTO at rangle.io

Defining a ReallyBasic Directive

.directive('acmeUser', function () { return { restrict: 'E', // vs 'A', 'AE' replace: true, scope: {}, // vs 'true', 'null' template:'<span>user</span>' }; })

Page 14: Developing Custom Directives by Yuri Takhteyev, CTO at rangle.io

Transclusion

.directive('acmeUser', function () { return { restrict: 'E', replace: true, transclude: true, scope: {}, template:'<span>user ' + '<div ng-transclude/></span>' }; })

Page 15: Developing Custom Directives by Yuri Takhteyev, CTO at rangle.io

An External Template

.directive('acmeUser', function () { return { restrict: 'E', // vs 'A', 'AE' replace: true, scope: {}, templateUrl:'/users/user.html' }; })

Page 16: Developing Custom Directives by Yuri Takhteyev, CTO at rangle.io

Linking.directive('acmeUser', function () { var directive = { restrict: 'E', replace: true, scope: {}, templateUrl: '/user/user.html' }; directive.link = function(scope, element,

attrs) { ... }; return directive; })

Page 17: Developing Custom Directives by Yuri Takhteyev, CTO at rangle.io

External communication:services

.directive('acmeUser', ['users', function (users) { ... directive.link = function(scope, element, attrs) { scope.name = users.getName(); ... }; ... }])

Page 18: Developing Custom Directives by Yuri Takhteyev, CTO at rangle.io

External communication:attributes, string

<acme-user username="alice"></acme-user>

directive.scope = { username: '@username'};

directive.link = function(scope, element, attrs){ scope.user = users.getUser(scope.username);};

Page 19: Developing Custom Directives by Yuri Takhteyev, CTO at rangle.io

External communication:attributes, 2-way-binding

<acme-user username="user"></acme-user>

directive.scope = { username: '=username'};

directive.link = function(scope, element, attrs){ scope.user = users.getUser(scope.username);};

Page 20: Developing Custom Directives by Yuri Takhteyev, CTO at rangle.io

External communication:binding callbacks

<acme-user username="user" on-ban="handleBan(user)"></acme-user>

directive.scope = { fireBan: '&onBan'};

directive.link = function(scope, element, attrs){ ... scope.fireBan(); ...}; ☛ Consider using a service

Page 21: Developing Custom Directives by Yuri Takhteyev, CTO at rangle.io

External communication:attribute processing

<acme-user username="{{user}}"></acme-user>

directive.scope = {};

directive.link = function(scope, element, attrs){ ... attrs.username ...};

Page 22: Developing Custom Directives by Yuri Takhteyev, CTO at rangle.io

External communication:$parsing expressions

<acme-user username="{{user}}" cost="hours * rate"></acme-user>

directive.link = function(scope, element, attrs) { var userData = users.getUser(scope.username); var getCost = $parse(attrs.cost); scope.cost = getCost({ rate: userData.rate, hours: userData.cost, discount: userData.discount });};

Page 23: Developing Custom Directives by Yuri Takhteyev, CTO at rangle.io

When to use compile:rarely

<acme-user username="{{user}}" cost="hours * rate" repeat="5"></acme-user>

directive.compile = function (tElement, tAttrs) { var wrapper = angular.element('<div></div>'); for (var i=0; i<tAttrs.repeat; i++) { wrapper.append(tElement.clone()); } tElement.replaceWith(wrapper); return function (scope, iElement, iAttrs) { ... };};

Page 24: Developing Custom Directives by Yuri Takhteyev, CTO at rangle.io

Directives & Services

☛ Use a service to control a directive

$ionicSlideBoxDelegate.$getByHandle('users') .update();

Page 25: Developing Custom Directives by Yuri Takhteyev, CTO at rangle.io

Directives, Services & DOM

☛ Offload DOM processing to a service

directive.link = function(scope, element, attrs) { scope.scroller = scroller.makeScroller( attrs.id, element);};

Page 26: Developing Custom Directives by Yuri Takhteyev, CTO at rangle.io

Testing Directives

element = $compile(template)(scope);element.click();user.select.should.have.been.calledOnce;

☛ But focus on services!

Page 27: Developing Custom Directives by Yuri Takhteyev, CTO at rangle.io

Thank You.Contact: [email protected] http://yto.io @qaramazov

This presentation: http://yto.io/xdir