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
в другом месте.