如何防止指令绑定到Angular中控制器范围内的元素?

时间:2015-02-06 12:01:11

标签: angularjs angularjs-directive

我有一个Angular应用程序,MyApp,依赖于外部模块(两个不同的地图解决方案),我需要它们但是在不同的控制器中(甚至在MyApp中的不同模块)。

问题是两个模块都有绑定到同一个参数的指令(在本例中为'center'),这导致它们都操作单个元素。我想要的是一个指令在一个控制器内是活动的而另一个指令在另一个控制器内是活动的 - 所以不要让它们同时处理我的元素。

我不想更改外部模块的代码以实现此目的。

2 个答案:

答案 0 :(得分:0)

我发现这是一个非常有趣的问题。下面的答案是不完整的,坦率地说,有点hackish,但它演示了一种方法来重命名另一个模块中的指令而不修改模块本身的来源。有很多工作要做,以使其在生产准备就绪的任何地方,并且绝对可以改进。

解决方案的注意事项是,一旦指令重命名," old"名称将不再有效。它还取决于某些角度约定,这些约定可能会随着未来版本等而改变,因此它不是未来的证据。对于复杂的指令,它也可能会失败,我还没有对它进行任何测试。

然而,它表明它可以完成,并且该概念可能导致特征角度需求(能够命名外部模块以防止诸如您正在经历的冲突之类的冲突)。

我认为如果您的用例相当简单,这将解决您的问题,但我不建议在一般情况下使用它。

(function () {
          var util = angular.module('util', [], function ($compileProvider) {
            util.$compileProvider = $compileProvider
          })
          .factory('$directiveRename', function () {
              var noop = function () { return function () { }; };
              return function (module, directive, newDirective) {
                  var injector = angular.injector(['ng', module]);

                  var directive = injector.get(directive + 'Directive');
                  if(directive)
                  {

                      //there can be multiple directives with the same name but different priority, etc.  This is an area where this could definitely be improved.  Will only work with simple directives.
                      var renamedDirective = angular.copy(directive[0]);
                      delete renamedDirective['name'];

                      util.$compileProvider.directive(newDirective, function () {
                          return renamedDirective;
                      });
                   }

                  //noop the old directive
                  //http: //stackoverflow.com/questions/16734506/remove-a-directive-from-module-in-angular
                  angular.module(module).factory(directive + 'Directive', noop);
              };
          });
      })();

使用示例:

angular.module('app', ['module1', 'module2', 'util'])
  .run(function ($directiveRename) {

      $directiveRename('module1', 'test', 'testa');
      $directiveRename('module2', 'test', 'testb');
  });

答案 1 :(得分:0)

一个替代的,稍微不那么强硬的答案。

在包含angular的脚本标记(在加载任何其他模块之前)

之后立即添加以下内容
<script type="text/javascript">

        var angularModule = angular.bind(angular, angular.module);

        angular.module = function (moduleName, requires, configFn) {
            var instance = angularModule(moduleName, requires, configFn);

            var directive = instance.directive;

            instance.directive = function (directiveName, directiveFactory) {

                //You can rename your directive here based on the module and directive name.  I don't know the module and directive names for your particular problem.  This obviously could be generalized.
                if (instance.name == 'module1' && directiveName == 'test') {
                    directiveName = 'testa';
                }

                if (instance.name == 'module2' && directiveName == 'test') {
                    directiveName = 'testb';
                }

                return directive(directiveName, directiveFactory);
            }

            return instance;
        };
</script>

这可以通过拦截对module.directive的调用来实现,并允许您在创建指令之前重命名该指令。