Могу ли я сделать две вещи одновременно в структурной директиве? - PullRequest
0 голосов
/ 15 ноября 2018

Я хотел бы создать структурную директиву, которая будет вести себя следующим образом:

<p *myDirective="condition">This is some text</p>
  • Если condition равно false, то тег <p> равен , а не отображается вообще.
  • Если condition равно true, то тег <p> отображается с дополнительным атрибутом class.

Итак, либо есть Ничего рендеринга, или:

<p class="my-added-class">This is some text</p>

Другими словами, это немного похоже на *ngIf, но с дополнительным поведением.

Я могу найти примеры того, как сделатьповедение include / exclude (на самом деле такой пример есть в Angular docs ).Я также могу найти примеры того, как добавить класс к элементу , используя Renderer2 API .

Однако я не вижу, как я могу объединить эти методы, потому что первыйМетод манипулирует viewContainer для создания встроенного представления , тогда как второй метод использует средство визуализации для манипулирования элементом .

Есть ли способсделать это? Можно ли как-то создать встроенное представление, а затем манипулировать элементами, которые оно создает?Или я могу манипулировать шаблоном, чтобы изменить способ отображения вида?

[ПРИМЕЧАНИЕ: @HostBinding не работает со структурными директивами, так что это не вариант]

Ответы [ 2 ]

0 голосов
/ 15 ноября 2018

Другой способ

, просто чтобы поиграть:)

Использование Renderer2 универсально безопасно

import {
  Directive,
  Renderer2,
  TemplateRef,
  ViewContainerRef,
  ElementRef,
  Input, OnInit } from '@angular/core';

@Directive({
  selector: '[appMy]'
})
export class MyDirective implements OnInit{
  constructor(
  private templateRef: TemplateRef<any>,
  private viewContainer: ViewContainerRef,
  private renderer: Renderer2) { }
  @Input() set appMy(condition: boolean) {
   if (condition) {
     this.viewContainer.createEmbeddedView(this.templateRef);
    } else  {
     this.viewContainer.clear();
   }
  }
  ngOnInit() {
    const elementRef = this.viewContainer.get(0).rootNodes[0] as ElementRef;
    this.renderer.addClass(elementRef, 'myclass');
  }
}

По пути @Pankaj, но с рендерером

@Input() set appMy(condition: boolean) {
   if (condition) {
     const view = this.viewContainer.createEmbeddedView(this.templateRef);
     this.renderer.addClass(view.rootNodes[0], 'myclass');
   } else  {
     this.viewContainer.clear();
   }
  }
0 голосов
/ 15 ноября 2018

Я бы подумал о добавлении класса в DOM, когда он удовлетворял выражению, переданному ему (внутри сеттера). Вы можете получить зависимость ElementRef внутри директивы и добавить к ней class, что является правдой.

@Input() set myDirective(condition: boolean) {
  if (condition) {
    this.viewContainer.createEmbeddedView(this.templateRef);
    this.elementRef.nativeElement.nextElementSibling.classList.add('my-added-class'); // renderer API can be used here
    // as Alex and Yurzui suggested
    // const view = this.viewContainer.createEmbeddedView(this.templateRef); 
    // view.rootNodes[0].classList.add('some-class')
  } else if (condition) {
    this.viewContainer.clear();
  }
}
...