如何在 angular js 中管理来自控制器的指令
how to manage a directive from your controller in angular js
我正在寻找 angular 模式来实现离子库使用其 delegate 模式所做的事情。
当您在视图中使用它的指令 (<ion-slide-box>
) 时,您可以自动在控制器中注入某种与指令对象关联的服务 ($ionicSlideBoxDelegate
),您可以使用它来控制它的方法如下:
$ionicSlideBoxDelegate.start() // Start sliding again if the slideBox was stopped
$ionicSlideBoxDelegate.stop() // Stop sliding
$ionicSlideBoxDelegate.next() // Go to the next slide.
$ionicSlideBoxDelegate.previous() // Go to the previous slide
//...
我最好的尝试:
- 创建一个仅接收一个参数(委托服务对象)的独立作用域的指令
- 在控制器中实例化此委托服务的新实例并将其附加到
$scope
- 在视图中将实例传递给指令的委托服务
下面是一些代码来说明我的解决方案。在这个例子中,我试图创建一个 假进度条 指令,它将像一个正常的进度条一样工作,但它会自动前进,除非我们告诉它 stop
。它永远不会达到 100%,除非通过调用 complete
.
告知这样做
指令及其附加的处理程序(或委托):
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: -> # ...
在你的控制器中:
angular.module("app", ["ui.bootstrap", "fakeProgressbar"])
.controller "fakeProgressbarExampleController", ($scope, FakeProgressbarHandler) ->
$scope.fakeProgressbarHandler = new FakeProgressbarHandler()
$scope.fakeProgressbarHandler.start() # start animation inmediately
# now you can do `$scope.fakeProgressbarHandler.stop()` or `$scope.fakeProgressbarHandler.complete()`
在您看来:
<fake-progressbar handler="fakeProgressbarHandler"></fake-progressbar>
可在此处找到此工作代码的完整示例:http://plnkr.co/edit/Ehsuu1nKxeu2W7ktTVFC?p=preview
问题:
当然,问题是如何摆脱必须将 fakeProgressbarHandler
附加到作用域以便稍后将其传回指令。
ionic 委托模式 似乎自动实现了这一点。
离子代表并没有太多的魔力。每当使用该指令时,控制器都会向委托服务注册一个实例。例如在 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);
}
);
委托代码主要在这里找到:
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);
}
};
};
这里是一个简单的注册示例(未经测试):
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>
我正在寻找 angular 模式来实现离子库使用其 delegate 模式所做的事情。
当您在视图中使用它的指令 (<ion-slide-box>
) 时,您可以自动在控制器中注入某种与指令对象关联的服务 ($ionicSlideBoxDelegate
),您可以使用它来控制它的方法如下:
$ionicSlideBoxDelegate.start() // Start sliding again if the slideBox was stopped
$ionicSlideBoxDelegate.stop() // Stop sliding
$ionicSlideBoxDelegate.next() // Go to the next slide.
$ionicSlideBoxDelegate.previous() // Go to the previous slide
//...
我最好的尝试:
- 创建一个仅接收一个参数(委托服务对象)的独立作用域的指令
- 在控制器中实例化此委托服务的新实例并将其附加到
$scope
- 在视图中将实例传递给指令的委托服务
下面是一些代码来说明我的解决方案。在这个例子中,我试图创建一个 假进度条 指令,它将像一个正常的进度条一样工作,但它会自动前进,除非我们告诉它 stop
。它永远不会达到 100%,除非通过调用 complete
.
指令及其附加的处理程序(或委托):
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: -> # ...
在你的控制器中:
angular.module("app", ["ui.bootstrap", "fakeProgressbar"])
.controller "fakeProgressbarExampleController", ($scope, FakeProgressbarHandler) ->
$scope.fakeProgressbarHandler = new FakeProgressbarHandler()
$scope.fakeProgressbarHandler.start() # start animation inmediately
# now you can do `$scope.fakeProgressbarHandler.stop()` or `$scope.fakeProgressbarHandler.complete()`
在您看来:
<fake-progressbar handler="fakeProgressbarHandler"></fake-progressbar>
可在此处找到此工作代码的完整示例:http://plnkr.co/edit/Ehsuu1nKxeu2W7ktTVFC?p=preview
问题:
当然,问题是如何摆脱必须将 fakeProgressbarHandler
附加到作用域以便稍后将其传回指令。
ionic 委托模式 似乎自动实现了这一点。
离子代表并没有太多的魔力。每当使用该指令时,控制器都会向委托服务注册一个实例。例如在 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);
}
);
委托代码主要在这里找到:
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);
}
};
};
这里是一个简单的注册示例(未经测试):
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>