繁体   English   中英

使用$ provide重命名第三方Angular Directive - 不工作

[英]Renaming 3rd party Angular Directive using $provide - not working

我在一个大型网站中使用了优秀的Angular UI引导程序以及我自己的许多指令。 为了整洁起见,我寻找了一种方法来重命名几个uib指令而不触及他们的代码,并遇到了几个SO问题,看起来是一个很好的解决方案。 麻烦的是它不适合我。 这是我的代码。

angular.module('s4p').config(function($provide, $compileProvider){

    console.log("I am logged in the console");

    $provide.decorator('uibPaginationDirective', function($delegate){

        console.log("I am not logged");

        $compileProvider.directive('s4pPaging', function(){
           return $delegate[0];
        });

        return function() { return angular.noop };

    });
});

我在那里放了几个console.log来看看它到底有多远,我可以看到它甚至没有运行装饰器。 起初我认为这可能是uiPaginationDirective中的一个简单的拼写错误,但如果我改变了一个字符,那么我在控制台中会出现一个很大的注入错误。 所以,它肯定找到原始指令,但装饰功能没有运行。

我做的事真的很蠢吗?

编辑 :只是为了澄清,我正在使用ng-annotate来简化依赖注入,因此.config()中没有依赖项数组

编辑2 :如果页面上没有使用该元素,装饰器不会运行,我没有意识到。 因此,如果您使用旧元素,则装饰器会运行,但如果您使用新别名,则根本不会发生任何事情。 我开始认为我发现的这段代码可能永远不会有效,除非使用原始指令将装饰器放入装备中。

编辑3 :我为此添加了一笔赏金,因为找到解决方案会很好。 即使没有人能修复示例代码,也必须有其他方法来重命名第三方指令而不更改它? 我找到了一个名为“alias”的插件来做这个,但我真的不想使用更多的第三方代码,我想了解解决方案。

编辑4 :我一直在玩我借用的代码来制作这个,你可以在下面的插件中看到 - http://plnkr.co/edit/3aDEed?p=preview我认为它只有用,因为演示使用了HTML中的原始指令,后跟重命名的指令。 如果从HTML中删除原始文件,则它们都会消失。 我假设是因为指令装饰器仅在第一次使用该指令时运行。 因此,我的任务现在是找到一种方法让装饰器在不使用原始指令的情况下运行,或者寻找更好的方法来重命名第三方指令......

编辑5 :我尝试了其他似乎是别名插件似乎在幕后做的事情。

angular.module('s4p').directive('s4pPaging', function(){

    return {
        restrict: 'EA',
        replace: true,
        template: '<uib-pagination class="s4pPaging"></uib-pagination>'
    }

});

...但不幸的是我得到以下错误。

错误:[$ compile:multidir]多个指令[s4pPaging(module:s4p),uibPagination]要求模板:...

我不明白为什么他们都要求模板。 我原以为s4p-paging会被uib-pagination和被复制到uib-pagination元素的所有属性所取代。 显然,我不明白为什么像这样简单的东西不起作用。

基于我对另一个问题的旧解决方案 ,您需要在页面上使用至少一个指令实例,因为这是角度DI工作的方式。 只有当它第一次使用时,它才会懒惰地实例化任何工厂。

正如我在前面的评论中提到的,您可以通过获取指令工厂(指令名称后缀为“Directive”一词)来获得任何指令配置$injector.get('directiveNameDirective')

这是一个解决问题的抽象(记住这将解决命名冲突问题以及原始线程,这也是更模块化,更容易设置,只需在您的应用程序中调用一个配置)。

您可以从我的存储库中获取该模块

angular.module('renameDirectiveUtil', [])
.provider('renameDirective', ['$provide' , '$compileProvider' , function($provide, $compileProvider){
    var directiveSet;

    this.setConfig = function setConfig(config){
      directiveSet = config;

       angular.forEach(directiveSet, function iterator(targetDir, sourceDir){
          sourceDir +=  'Directive';
          //Set up decorators
          $provide.decorator(sourceDir, function decorate($delegate){

             //Used to register a directive. $delegate is the original directive definition.
             $compileProvider.directive(targetDir, function(){
                return $delegate[0];
             });

              //This will remove the original directive definition, if not just return the delegate as is.
              return function() { return angular.noop };
          });
      });
    };

    this.$get  = ['$injector', function renameDirectiveService($injector){
      return { 
        rename : function rename(){
          angular.forEach(directiveSet, function(_,dir){
             var sourceDir = dir + 'Directive';
            //Just return the original directive definition which will trigger the decorator and redefine itself while renaming the new one.
            $injector.get(sourceDir);
          });
        }
      }
    }];
}]).run(['renameDirective',function(renameDirective){
  renameDirective.rename();
}]);

您现在需要做的就是将其作为模块中的依赖项包含在内。

 angular.module('plunker', ['renameDirectiveUtil']);

并通过提供格式为{sourceDirectiveName : targetDirectiveName }的配置对象来配置它。

app.config(['renameDirectiveProvider',function(renameDirectiveProvider){
  renameDirectiveProvider.setConfig({
    'property' : 'cmProperty'
  });
}]);

这是一个掠夺者

试试这个:

var app = angular.module('plunker', ['ui.bootstrap', 'myDirectives']);

angular.module('myDirectives', [])
.directive('myPagination', function($injector) {
  return angular.copy($injector.get('uibPaginationDirective'))[0];
});

app.controller('PaginationDemoController', function($scope) {});

<body ng-app="plunker">
  <div ng-controller="PaginationDemoController">
    <my-pagination total-items="20" ng-model="currentPage"></my-pagination>
  </div>
</body>

这无需首先在页面上使用原始指令。

查看工作的plunker

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM