扩展 AngularJs 指令

IT技术 javascript angularjs angularjs-directive angular-ui-bootstrap bower
2021-02-07 22:06:29

我想对第 3 方指令(特别是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
  };
}]);

但我也想让 Angular-Bootstrap 与 Bower 保持同步。一旦我运行bower update,我将覆盖我的更改。

那么我该如何从这个 bower 组件中单独扩展这个指令呢?

5个回答

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

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

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

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

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

嘿,这个答案真的很好,但我找不到任何关于指令“优先级”属性的文档。我发现的只是一个宣传语,上面写着“你可以使用它”,但找不到任何实际的例子。
2021-03-17 22:06:29
谢谢@sh0ber,这正是我需要的。你之前的回答也对我有帮助,关于:3rd 方服务。
2021-03-29 22:06:29
@Ciel 指令 API 信息显然已移至此处$compile文档
2021-04-10 22:06:29

TL; DR - 给我演示!


     Big Demo Button     
 


使用$provide'sdecorator()来装饰第三方的指令。

在我们的例子中,我们可以像这样扩展指令的范围:

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

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

一旦我们得到它,我们就可以获取它的作用域对象并根据需要扩展它。请注意,所有这些都必须在config块中完成

一些笔记

  • 有人建议简单地添加一个具有相同名称的指令,然后设置其优先级。除了没有语义(这甚至不是一个词,我知道……),它还带来了一些问题,例如,如果第三方指令的优先级发生变化怎么办?

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

@EliranMalka 是的,bindToController是在 v1.3 中引入的。但请注意,这不应被视为替代解决方案,这仅适用于使用bindToController属性设置原始指令的特定情况好主意,我会将此作为答案发布:)
2021-03-23 22:06:29
嗨@EliranMalka 检查我的plunker plnkr.co/edit/0mvQjHYjQCFS6joYJdwK 希望这会帮助某人
2021-03-28 22:06:29
我建议你试一试@sh0ber 的回答(创建另一个仅用于发出事件的指令)。
2021-04-01 22:06:29
关于这个答案的快速说明(效果很好),“paneDirective”中的“指令”确实有目的;-) 我花了一段时间才弄清楚:stackoverflow.com/questions/19409017/...,请参阅已接受的回答。
2021-04-02 22:06:29
链接decorator()已损坏(更新为docs.angularjs.org/api/auto/service/$provide#decorator
2021-04-07 22:06:29

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

+1 为单挑。很高兴知道。我猜 bower 的 angular-bootstrap 和 angular-ui 的 bootstrap 组件不同步。
2021-03-30 22:06:29

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

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

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

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)
});

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

是的,angular.merge应该已经使用了,我会更新示例
2021-03-21 22:06:29
angualr.merge 已弃用,请参阅docs.angularjs.org/api/ng/function/angular.merge您应该使用类似 Lodash(由 AnguarJs 推荐)之类的东西 lodash.com/docs/4.17.15#merge
2021-04-02 22:06:29
这太棒了,正是我用自己的变量扩展隔离范围指令所需要的!!我确实发现 angular.extend 不会深度复制对象,所以这用这个替换了 paneDirective 的范围对象。另一种选择是 angular.merge,它将保留 PaneDirective 的原始范围并添加/合并此处定义的变量。
2021-04-04 22:06:29

这是将绑定扩展到具有该bindToController属性的指令的不同场景的另一种解决方案

注意:这不是此处提供的其他解决方案的替代方案。它仅解决原始指令设置为bindToController.