AngularJS: Как правильно включить дочерние элементы в пользовательскую директиву?

Вот некоторый код: ссылка

Я пытаюсь создать директиву, которая оборачивает своих детей в какой-то шаблон. Но если у детей есть ng-if контролируя их внешний вид, "включение" не работает. Ну, вроде как, но, как вы можете видеть, ng-if логика не проходит правильно.

Я хотел бы знать, как это исправить, но также и где (если где-нибудь) это описано в Angular Docs.

2 ответа

Решение

Проблема в том, что Angular изначально заменяет ngIf с комментарием, который используется для отслеживания места размещения условного кода. Это проще всего увидеть на примере.

Ваш HTML:

<div control-group>
  <label>Test</label>
  <input type="text" ng-model="editing.name" />
  <span class="text-error" ng-if="editing.name.length != 3"> Name must be 3 characters </span>
</div>

Похоже, это внутри вашей функции transclude cloned переменная (transclude(function (cloned) {):

<div control-group>
  <label>Test</label>
  <input type="text" ng-model="editing.name" class="ng-valid ng-dirty">
  <!-- ngIf: editing.name.length != 3 -->
</div>

Итак, элемент с классом text-error что вы фильтруете (ниже) не в cloned, Просто комментарий есть.

var inputsAndMessages = cloned.filter('input, button, select, .text-error');

Поскольку вы включаете только те элементы, которые соответствуют приведенному выше фильтру ngIf комментарий потерян.

Решение также состоит в том, чтобы отфильтровать комментарии и добавить их в свое приложение (таким образом, Angular сохраняет свою контрольную точку для ngIf). Один из способов сделать это - заменить вышеприведенное на это (используя тот факт, что html-комментарий относится к типу узла 8)

var messages = cloned.filter(function(){ return this.nodeType == 8; }); //comments

var inputs = cloned.filter('input, button, select')

var inputsAndMessages = inputs.add(messages);

Рабочий плункер

Вы должны указать директиве, где разместить дочерние элементы с помощью ng-transclude директива: ( plnkr)

 template: "<div class='control-group' ng-transclude>" +
                 "<label class='control-label' for=''></label>" +
                 "<div class='controls'></div>" +
              "</div>",

Из документов:

Директива, которая отмечает точку вставки для включенного DOM ближайшей родительской директивы, которая использует transclusion.

Любое существующее содержимое элемента, на котором размещена эта директива, будет удалено до вставки включенного содержимого.

Я не был уверен, каково было ваше намерение, так как у вас есть input а также label как в шаблоне, так и в качестве детей в HTML. Вы можете разместить свой ng-transclude в другом месте.

Другие вопросы по тегам