2015-11-04 4 views
0

Я пытаюсь создать директиву с именем availableTo, которая может переключаться между двумя разными шаблонами в зависимости от некоторого сообщения. Например, если поле является input с директивой ng-model, сначала мне нужно будет изменить его на чтение только с использованием тега <span>. До сих пор мой код может переключать вид только для чтения, но я не могу показаться, чтобы переключить его обратно в input:угловая директива: переключаться между двумя шаблонами динамически

var directive = { 
     restrict: 'A', 
     require: '?ngModel', 
     link: linkerFn, 
     replace: true 
    }; 

function linkerFn(scope, element, attrs, ngModelCtrl) { 

     var clonedElement = angular.copy(element); 
     var preOuterHTML = clonedElement[0].outerHTML; //this can save the <input> field html code 

     scope.$on('mode_changed', function() { 
      var curUserRole = userservices.getUserRole(); 

      if (attrs.availableTo == curUserRole) { 
       var e = $compile(preOuterHTML)(scope); 
       element.replaceWith(e); 
      } else { 
       var template = '<span>' + ngModelCtrl.$viewValue + '</span>'; 
       var e = $compile(template)(scope); 
       element.replaceWith(e); 
      } 

     }); //scope.$on 
    } //linkerFn 

Для input поле:

<input name="test1" class="form-control" ng-model="name" placeholder="Name 1" available-to="ADMIN"/> 

Я также заметил, что когда-то я измените шаблон в блоке else выше, элемент повторно отображает, а preOuterHTML больше не содержит оригинальный элемент html. Мне кажется, это невозможно для меня, но я хотел бы услышать некоторые мнения экспертов. Thanks

ответ

3

element.replaceWith(e); Не делайте этого. В Angular, если вы пытаетесь изменить DOM напрямую, вы по определению делаете это неправильно. Вы должны сидеть сложа руки и позволить Угловому делать работу.

Если вам нужно заменить весь шаблон директивы, довольно простой подход заключается в использовании ng-include с переменной области, содержащей требуемый условный templateUrl, например.

var directive = { 
    // ... 
    template: '<div ng-include="myTemplateUrl"></div>', 
    link: function(scope, el) { 
    if (/* whatever */) { 
     scope.myTemplateUrl="templates/foo.html"; 
    } else { 
     //...etc 
    } 
    }, 
}; 

(Это действительно добавляет дополнительный узел DOM к дереву, но это обычно безвредны.)

Это звучит, как в вашем случае вам не нужно идти так далеко, хотя; простой ng-if внутри вашего шаблона, вероятно, достаточно для обмена между вашими только для чтения <span> и <input>.

+0

_ «если вы пытаетесь изменить DOM напрямую, вы по определению делаете это неправильно» _ - Итак, вы действительно предполагаете, что сам Угловой делает это неправильно? И чье определение вы имеете в виду? – zeroflagL

+0

@zeroflagL Я думаю, что вся суть этого утверждения заключается в том, что * только * угловой должен изменить DOM. В 99% случаев люди используют методы 'element', потому что они не знают, как правильно построить приложение таким образом, чтобы вместо него могли быть угловые. Ответ предоставил лучший способ для этого варианта использования. – Claies

+0

@ Даниэль Бек, большое спасибо за решение. Поскольку я пытаюсь сделать директиву как можно более общим, я думаю, мне нужно будет создать шаблон для всех возможных полей ввода, таких как 'input',' select', 'checkbox'. Кажется, что нет прямого способа кэширования исходного шаблона элемента в Angular. – TonyGW

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