Привязать ссылочную переменную шаблона как тип директивы атрибута

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

@Directive({
  selector: "[filter]ng-template"
})
export class FilterableTemplateDirective extends TemplatePortalDirective {

  @Input() filter: string;

  constructor(templateRef: TemplateRef<any>, viewContainerRef: ViewContainerRef
  {
    super(templateRef, viewContainerRef);
  }
}

а моя директива атрибутов с именем TemplateSelector имеет @Input, который также используется как селектор по атрибуту:

@Directive({
  selector: "[templateSelector]"
})
...
@Input("templateSelector") templates: FilterableTemplateDirective[]

Теперь предположим, что у меня есть следующий шаблон:

<div templateSelector="[templateA, templateB]"></div>
<ng-template filter="div[data-type-a]" #templateA>
...
</ng-template>
<ng-template filter="div[data-type-b]" #templateB>
...
</ng-template>

Итак, когда я пытаюсь получить доступ к this.templates из метода внутри TemplateSelector, я получаю массив, но он имеет тип TemplateRef, то есть простой ng-template, без дополнительных полей, хотя во время отладки я видел это FilterableTemplateDirective был построен дважды, до того, как был назначен массив с шаблонами, а также был назначен filter, хотя назначение фильтров произошло позже, чем присвоение массива шаблонам. Я пробовал использовать при построении массива, например:

<div templateSelector="[templateA as FilterableTemplateDirective, templateBtemplateA as FilterableTemplateDirective]"></div>

or so:

<div templateSelector="[<FilterableTemplateDirective>templateA, <FilterableTemplateDirective>templateBtemplateA]"></div>

ни то, ни другое не удалось, приложение просто вылетает, говоря, что ожидал конец массива вместо as или угловых скобок ...


person Jyrkka    schedule 23.03.2018    source источник


Ответы (2)


Если у вас есть гибкость в шаблоне, вы можете добиться желаемого, используя @ContentChildren следующим образом. :

<div templateSelector>
  <ng-template filter="div[data-type-a]">
    ...
  </ng-template>
  <ng-template filter="div[data-type-b]">
    ...
  </ng-template>
</div>

и ваша директива templateSelector:

@Directive({
  selector: "[templateSelector]"
})

...

@ContentChildren(FilterableTemplateDirective) 
templates: QueryList<FilterableTemplateDirective>;

При тегировании элементов с помощью переменных шаблона вы ограничены тем, что не можете указать Angular, что вы хотите от этого элемента. С шаблонными запросами, такими как @ContentChildren, @ContentChild, @ViewChild и @ViewChildren, вы можете гибко сообщать Angular, нужна ли вам директива / компонент от него, или ElementRef, или ViewContainerRef (и, возможно, некоторые другие токены).

person Sam Herrmann    schedule 23.03.2018
comment
Да, определенно вариант, но это не вопрос гибкости и больше логики, я бы предпочел оставить шаблоны за пределами целевого элемента, если это возможно ... - person Jyrkka; 23.03.2018

Что ж, теперь кажется, что ответ очевиден и лежит на поверхности - просто добавить свойство exportAs в Directive decorator, а затем назначить ссылку на ссылочную переменную шаблона, что очень похоже на _3 _...

person Jyrkka    schedule 23.03.2018