[英]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>
這無需首先在頁面上使用原始指令。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.