Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
hjzheng opened this issue Jun 2, 2015 · 0 comments
Open

Comments

@hjzheng
Copy link
Owner

hjzheng commented Jun 2, 2015

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant