4

Я использую превосходный Угловой пользовательский бутстрап на большом сайте наряду с множеством моих собственных директив. Для аккуратности я искал способ переименовать пару директив 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.logs туда, чтобы увидеть, насколько это становится, и я вижу, что это даже не работает декоратора. Сначала я подумал, что это может быть простой ошибкой орфографии в uiPaginationDirective, но если я изменю хотя бы один символ, тогда я получаю большую ошибку инжектора в консоли. Таким образом, он определенно находит исходную директиву, но функция украшения не работает.

Я делаю что-то действительно глупое?

Редактировать: Просто чтобы прояснить, я использую нг-Аннотировать для упрощения инъекции зависимостей, следовательно, не массив зависимостей в .config()

Edit 2: Декоратор не работает если элемент не используется на странице, чего я не понял. Итак, если вы используете старый элемент, то декоратор действительно работает, но если вы используете новый псевдоним, тогда ничего не происходит вообще. Я начинаю думать, что этот код, который я нашел, возможно, никогда не работал, если оригинальная директива не используется, чтобы выгнать декоратора в механизм.

Редактировать 3: Я добавил щедрость к этому, потому что было бы неплохо найти решение. Даже если никто не может исправить код примера, должны быть другие способы переименования директивы третьей стороны, не меняя ее? Я нашел плагин под названием «alias», который делает это, но я действительно не хочу использовать дополнительный сторонний код, и я хочу понять решение.

Edit 4: Я играл с кодом, который я одолжил, чтобы сделать это, которые вы можете увидеть в следующем plunkr - 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>' 
    } 

}); 

... но, к сожалению, я получаю следующее сообщение об ошибке.

Error: [$compile:multidir] Multiple directives [s4pPaging (module: s4p), uibPagination] asking for template on:...

Я не понимаю, почему они оба просят шаблон. Я бы предположил, что s4p-пейджинг будет заменен на uib-pagination и все атрибуты, скопированные на элемент uib-pagination. Ясно, что я не понимаю, почему что-то простое не работает.

+0

Что в $ делегатом [0], из любопытства? – matmo

+0

Я не уверен. Я получил код ответа на этот вопрос - http://stackoverflow.com/questions/26416206/directive-name-and-attribute-name-clashing – jonhobbs

+0

Вы можете просто создать экземпляр, выполнив '.run (['$ инжектор ', функция ($ инжектор) { $ injector.get (' propertyDirective '); }]); '. Я могу получить это в модульном режиме, если вы захотите. – PSL

ответ

3

Основываясь на моем old solution for another question, вам нужно будет использовать по крайней мере один экземпляр директивы на странице, так как это путь угловой DI работает. Он лениво создает экземпляр любой фабрики только тогда, когда она используется в первый раз.

Как я уже упоминал в своем комментарии ранее, вы можете получить любую директивную конфигурацию, получив фабрику директив (название директивы, помеченное словом «Директива») $injector.get('directiveNameDirective').

Вот абстракция для решения проблемы (помните, что это разрешит проблему конфликта имен, а также из исходного потока, и это более модульное и простое настроение с помощью всего одного вызова конфигурации в вашем приложении).

Вы можете get the module from my repository

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

Вот plunker

+0

Хмм, не уверен, что я делаю неправильно, но получаю сообщение об ошибке «Ошибка: [$ compile: multidir] Несколько директив [uibPagination, uibPagination] просят шаблон:

+0

ОК, я нашел проблему. Я изменил шаблон страницы, чтобы добавить s4p-paging в качестве атрибута в шаблон (идея состоит в том, что директива должна быть ограничена до «E» и не скомпилирована при использовании в качестве атрибута, но исходная версия может использоваться как атрибут). Теперь она работает. Большое спасибо. – jonhobbs

+0

@jonhobbs Добро пожаловать , – PSL

2

Попробуйте это:

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> 

Это работает без необходимости использовать оригинальную директиву на странице первой.

Смотрите working plunker

 Смежные вопросы

  • Нет связанных вопросов^_^