2015-6-2 使用$provide.decorator方法去扩展angular现有指令
hjzheng opened this issue · comments
HaoJu Zheng commented
使用$provide.decorator方法去扩展angular现有指令
angular.config(['$provide', function ($provide){
$provide.decorator('accordionGroupDirective', function($delegate) {
var directive = $delegate[0];
directive.templateUrl = "views/parts/accordion-unit.html";
angular.extend(directive.scope, { index:'@' });
return $delegate;
});
}]);
几个切入点
- 扩展scope参数
- 替换模板
- 扩展或替换controller
- 扩展link或compile
扩展scope参数
使用angular.extend方法合并scope对象,该方式在1.2.x下是好的,到了1.3就不work了,不过有workaround方法,就是直接向directive.$$isolateBindings对象里面push你的参数,可以参看下面的例子
$provide.decorator('alertDirective', function($delegate) {
var directive = $delegate[0];
//works on 1.2
/*angular.extend(directive.scope, {
apply: '&',
discard: '&'
});*/
//1.3.x bug: https://github.com/angular/angular.js/issues/10149
directive.$$isolateBindings.apply = {
attrName: 'apply',
mode: '&',
optional: true
};
directive.$$isolateBindings.discard = {
attrName: 'discard',
mode: '&',
optional: true
};
... ...
return $delegate;
});
替换模板
直接对directive对象的templateUrl或tenmplate属性直接赋上你的模板:
directive.templateUrl = "views/parts/accordion-unit.html";
directive.template = "<div>Just Test</div>";
扩展或替换controller
扩展或替换 controller 或者 link 方法:
替换是直接附上新的函数即可
扩展是使用JavaScript函数进行继承,将要扩展函数的this上的属性和方法,全部继承过来。具体可以参看gist, 具体还没实践,但是理论上肯定是可以的.
另一种扩展controller的方法,使用$controller,测试后有些问题(会丢失一些方法),大家可以研究一下(来自参考资料的方法)
app.config(function($provide) {
$provide.decorator('fooDirective', function($delegate, $controller) {
var directive = $delegate[0];
var controllerName = directive.controller;
directive.controller = function($scope, $timeout) {
angular.extend(this, $controller(controllerName, {$scope: $scope}));
$timeout(function() {
$scope.name = "from the decorator now";
}, 3000);
};
return $delegate;
});
});
扩展link或compile (来自参考资料的方法)
备份link函数对其进行扩展
app.config(function($provide) {
$provide.decorator('fooDirective', function($delegate) {
var directive = $delegate[0];
directive.scope.fn = "&";
//backup old link method 备份旧的link
var link = directive.link;
//extend compile 扩展compile
directive.compile = function() {
return function(scope, element, attrs) {
link.apply(this, arguments);
element.bind('click', function() {
scope.$apply(function() {
scope.fn();
});
});
};
};
return $delegate;
});
});
备份旧的compile方法,执行,对返回的link方法进行扩展
app.config(function($provide) {
$provide.decorator('fooDirective', function($delegate) {
var directive = $delegate[0];
var compile = directive.compile;
directive.compile = function(tElement, tAttrs) {
var link = compile.apply(this, arguments);
tElement.append('<div>Added in the decorator</div>');
return function(scope, elem, attrs) {
link.apply(this, arguments);
// We can extend the link function here
};
};
return $delegate;
});
});
Example
扩展Bootstrap-UI Alert Directive
扩展Bootstrap-UI Dropdown Directive
参考资料:
Experiment: Decorating Directives
AngularJS in Patterns (Part 2). Services.