扩展角度指令

Kyl*_*yle 114 javascript angularjs bower angularjs-directive angular-ui-bootstrap

我想对第三方指令(特别是Angular UI Bootstrap)做一个小修改.我只想添加到pane指令的范围:

angular.module('ui.bootstrap.tabs', [])
.controller('TabsController', ['$scope', '$element', function($scope, $element) {
  // various methods
}])
.directive('tabs', function() {
  return {
    // etc...
  };
})
.directive('pane', ['$parse', function($parse) {
  return {
    require: '^tabs',
    restrict: 'EA',
    transclude: true,
    scope:{
      heading:'@',
      disabled:'@' // <- ADDED SCOPE PROPERTY HERE
    },
    link: function(scope, element, attrs, tabsCtrl) {
      // link function
    },
    templateUrl: 'template/tabs/pane.html',
    replace: true
  };
}]);
Run Code Online (Sandbox Code Playgroud)

但我也想让Angular-Bootstrap与Bower保持同步.我一跑bower update,就会覆盖我的变化.

那么我该如何将这个指令与这个凉亭组件分开扩展呢?

Dan*_*Dan 96

解决此问题的最简单方法可能是在您的应用程序上创建一个与第三方指令同名的指令.这两个指令都将运行,您可以使用该priority属性指定其运行顺序(优先级较高的运行首先运行).

这两个指令将共享范围,您可以通过指令的link方法访问和修改第三方指令的范围.

选项2:您还可以通过简单地将自己的任意命名指令放在同一元素上来访问第三方指令的范围(假设两个指令都不使用隔离范围).元素上的所有非隔离范围指令都将共享范围.

进一步阅读: https ://github.com/angular/angular.js/wiki/Dev-Guide%3A-Understanding-Directives

注意:我之前的回答是修改第三方服务,而不是指令.

  • 谢谢@ sh0ber,这正是我所需要的.你之前的回答对我有帮助,重新:第三方服务. (3认同)
  • @Ciel指令API信息显然已被移动到`$ compile` doc [here](https://docs.angularjs.org/api/ng/service/$compile) (2认同)

Eli*_*lka 60

TL; DR - gimme tha demo!


     Big Demo Button     
 


使用$provide's decorator()来装饰第三方的指令.

在我们的例子中,我们可以扩展指令的范围,如下所示:

app.config(function($provide) {
    $provide.decorator('paneDirective', function($delegate) {
        var directive = $delegate[0];
        angular.extend(directive.scope, {
            disabled:'@'
        });
        return $delegate;
    });
});
Run Code Online (Sandbox Code Playgroud)

首先,我们请求pane通过传递它的名称来装饰该指令,并将其Directive作为第一个参数连接起来,然后我们从callback参数(它是与该名称匹配的指令数组)中检索它.

一旦我们得到它,我们就可以获得它的范围对象并根据需要进行扩展.请注意,所有这些都必须在config块中完成.

一些笔记

  • 建议只需添加一个具有相同名称的指令,然后设置其优先级.除了没有语义(我甚至不知道......),它会带来问题,例如,如果第三方指令的优先级发生变化会怎样?

  • JeetendraChauhan声称(我还没有测试过)这个解决方案在版本1.13中不起作用.

  • 关于这个答案的快速说明(效果很好),'paneDirective'中的'Directive'确实有目的;-)我花了一段时间才搞清楚:http://stackoverflow.com/questions/19409017/angular - 装饰指令,请参阅接受的答案. (2认同)
  • 嗨@EliranMalka检查我的plunker http://plnkr.co/edit/0mvQjHYjQCFS6joYJdwK希望这会帮助某人 (2认同)

pko*_*rce 8

虽然这不是您问题的直接答案,但您可能想知道http://angular-ui.github.io/bootstrap/的最新版本(在master中)添加了对禁用选项卡的支持.此功能是通过以下方式添加的:https: //github.com/angular-ui/bootstrap/commit/2b78dd16abd7e09846fa484331b5c35ece6619a2


kid*_*oca 6

另一种解决方案,您可以创建一个扩展它的新指令,而无需修改原始指令

解决方案类似于装饰器解决方案:

创建一个新指令并将您希望扩展的指令注入依赖项

app.directive('extendedPane', function (paneDirective) {

  // to inject a directive as a service append "Directive" to the directive name
  // you will receive an array of directive configurations that match this 
  // directive (usually only one) ordered by priority

  var configExtension = {
     scope: {
       disabled: '@'
     }
  }

  return angular.merge({}, paneDirective[0], configExtension)
});
Run Code Online (Sandbox Code Playgroud)

这样,您可以在同一个应用程序中使用原始指令和扩展版本

  • 这很棒,正是我需要用我自己的变量扩展一个isolate scope指令!! 我确实发现angular.extend不会深层复制对象,所以这会将paneDirective的范围对象替换为此对象.另一种方法是angular.merge,它将保留PaneDirective的原始范围并添加/合并此处定义的变量. (2认同)