Ответ 1
Создать собственную шаблонную директиву не сложно, нужно понимать две основные вещи
-
TemplateRef
содержит то, что внутри вашего<template>
-
ViewContainerRef
как прокомментировал Гюнтер, содержит представление шаблона и позволит вам встроить то, что внутри шаблона, в само представление.
Я буду использовать пример, который у меня был, когда я пытался решить эту проблему, мой подход не самый лучший для этого, но он поможет объяснить, как он работает.
Я также хочу уточнить, что вы можете использовать любой атрибут для своих шаблонов, даже если они уже используются встроенными директивами (очевидно, это не очень хорошая идея, но вы можете это сделать).
Рассмотрим мой подход к ngIfIn
(мой плохой подход)
<template [ngIfValue]="'make'" [ngIfIn]="obj">
This will print
</template>
<template [ngIfValue]="'notExistingValue'" [ngIfIn]="obj">
This won't print
</template>
Здесь у нас есть два шаблона, использующих два входа каждый ngIfIn
и ngIfValue
, поэтому мне нужна моя директива, чтобы получить шаблон этими двумя входами и получить их значения тоже, чтобы это выглядело так
@Directive({
selector : '[ngIfIn][ngIfValue]',
inputs : ['ngIfIn', 'ngIfValue']
})
Сначала мне нужно ввести два класса, которые я упомянул выше
constructor(private _vr: ViewContainerRef, private _tr: TemplateRef) {}
Мне также нужно кэшировать значения, которые я передаю через входы
_value: any;
_obj: any;
// Value passed through <template [ngIfValue]="'...'">
set ngIfValue(value: any) {
this._value = value;
}
// Value passed through <template [ngIfIn]="...">
set ngIfIn(obj: any) {
this._obj = obj;
}
В моем случае я зависел от этих двух значений, моя логика могла бы быть в ngOnInit
но она запускалась бы один раз и не прослушивала бы изменения в любом из входов, поэтому я поместил логику в ngOnChanges
. Помните, что ngOnChanges
вызывается сразу после проверки свойств, связанных с данными, и перед проверкой просмотра и дочерних элементов содержимого, если хотя бы одно из них изменилось (скопируйте и вставьте из документов).
Теперь я в основном копирую и вставляю логику NgIf (не так сложно, но похоже)
// ngOnChanges so this gets re-evaluated when one of the inputs change its value
ngOnChanges(changes) {
if(this._value in this._obj) {
// If the condition is true, we embed our template content (TemplateRef) into the view
this._vr.createEmbeddedView(this._tr);
} else {
// If the condition is false we remove the content of the view
this._vr.clear();
}
}
Как вы видите, это не так сложно: возьмите TemplateRef, возьмите ViewContainerRef, проделайте некоторую логику и внедрите TemplateRef в представление, используя ViewContainerRef.
Надеюсь, я прояснил себя и понял, как правильно их использовать. Вот plnkr с примером, который я объяснил.