hjzheng / CUF_meeting_knowledge_share

Record CUF team meeting knowledge share
121 stars 49 forks source link

2015-6-2 使用$provide.decorator方法去扩展angular现有指令 #34

Open hjzheng opened 9 years ago

hjzheng commented 9 years ago

使用$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;
    });
}]);

几个切入点

使用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.