angularjs - how to manage a directive from your controller in angular js -
i looking angular pattern achieves ionic library delegate pattern.
take slide box component, example:
when use directive (<ion-slide-box>
) in view can automatically inject in controller sort of service ($ionicslideboxdelegate
) associated directive object, can use control methods like:
$ionicslideboxdelegate.start() // start sliding again if slidebox stopped $ionicslideboxdelegate.stop() // stop sliding $ionicslideboxdelegate.next() // go next slide. $ionicslideboxdelegate.previous() // go previous slide //...
my best attempt:
- create directive isolated scope receives 1 parameter (the delegate service object)
- in controller instantiate new instance of delegate service , attach
$scope
- in view pass instance delegate service directive
here code illustrate solution. in example trying create fake progress bar directive act normal progress bar advance automatically, unless tell stop
. , never reach 100% unless told calling complete
.
the directive , attached handler (or delegate):
angular.module("fakeprogressbar", []) .directive 'fakeprogressbar', -> scope: handler: '=' restrict: 'e' replace: false template: ' <progressbar class="progress-striped active" max="handler.config.max" type="{{handler.config.type}}" value="handler.config.value"> {{ handler.config.value }} % </progressbar> ' .factory 'fakeprogressbarhandler', ($interval, $timeout, $q) -> class fakeprogressbar start: -> # ... success: -> # ... complete: -> # ... stop: -> # ...
in controller:
angular.module("app", ["ui.bootstrap", "fakeprogressbar"]) .controller "fakeprogressbarexamplecontroller", ($scope, fakeprogressbarhandler) -> $scope.fakeprogressbarhandler = new fakeprogressbarhandler() $scope.fakeprogressbarhandler.start() # start animation inmediately # can `$scope.fakeprogressbarhandler.stop()` or `$scope.fakeprogressbarhandler.complete()`
in view:
<fake-progressbar handler="fakeprogressbarhandler"></fake-progressbar>
a complete example of working code can found here: http://plnkr.co/edit/ehsuu1nkxeu2w7kttvfc?p=preview
the question:
the question is, of course, how rid of having attach fakeprogressbarhandler
scope later pass directive.
the ionic delegate pattern seems achieve automatically.
there isn't magic ionic delegates. whenever directive used, controller registers instance delegateservice. example in slidebox:
https://github.com/driftyco/ionic/blob/master/js/angular/directive/slidebox.js#l127
var deregisterinstance = $ionicslideboxdelegate._registerinstance( slider, $attrs.delegatehandle, function() { return $ionichistory.isactivescope($scope); } );
the delegate code found here:
https://github.com/driftyco/ionic/blob/master/js/utils/delegateservice.js
delegateservice.prototype._registerinstance = function(instance, handle, filterfn) { var instances = this._instances; instance.$$delegatehandle = handle; instance.$$filterfn = filterfn || truefn; instances.push(instance); return function deregister() { var index = instances.indexof(instance); if (index !== -1) { instances.splice(index, 1); } }; };
here simplified example of registering (untested):
var app = angular.module('app', []); app.controller('firstcontroller', function($scope, delegateservice) { $scope.start = function(handle) { delegateservice.getinstance(handle).start(); }; $scope.stop = function(handle) { delegateservice.getinstance(handle).stop(); }; }); app.controller('secondcontroller', function($scope, delegateservice) { $scope.startall = function() { object.keys(delegateservice._instances).foreach(function(handle) { delegateservice._instances[handle].start(); }); }; $scope.stopall = function(handle) { object.keys(delegateservice._instances).foreach(function(handle) { delegateservice._instances[handle].stop(); }); }; }); app.directive('somedirective', function(somedirectivedelegate, delegateservice) { return { scope: {}, controller: function($scope, $element, $attrs) { $scope.progress = { amount: 0 }; var delegate = new somedirectivedelegate($scope.progress); delegateservice._registerinstance(delegate, $attrs.handle); }, template: '<div>{{ progress.amount }}</div>' }; }); app.factory('somedirectivedelegate', function($interval) { function somedirectivedelegate(progress) { var interv; function stop() { if (interv) { $interval.cancel(interv); interv = null; } } function start() { stop(); interv = $interval(function() { progress.amount += 1; }, 100); } return { start: start, stop: stop, }; } return somedirectivedelegate; }); app.service('delegateservice', function() { this._instances = {}; this._registerinstance = function(instance, handle) { this._instances[handle] = instance; }; this.getinstance = function(handle) { return this._instances[handle]; }; });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script> <div ng-app='app'> <div ng-controller='firstcontroller'> <some-directive handle="1"></some-directive> <button ng-click="start(1)">start1</button> <button ng-click="stop(1)">stop1</button> <some-directive handle="2"></some-directive> <button ng-click="start(2)">start2</button> <button ng-click="stop(2)">stop2</button> </div> <hr> <div ng-controller='secondcontroller'> <button ng-click="startall()">start all</button> <button ng-click="stopall()">stop all</button> </div> </div>
Comments
Post a Comment