Как создать директиву, которая удаляет другие директивы, прежде чем они произойдут в Angular - PullRequest
0 голосов
/ 23 марта 2020

Я пытаюсь создать директиву, которая не позволит запустить другую директиву. Я попытался использовать как структурную, так и неструктурную директиву для выполнения sh этого, и ни одна из них не сработала.

Простое html Я использую:

<p appRemover appColor>
  Start editing to see some magic happen :)
</p>

Давайте скажем, у меня есть директива цвета, которая просто меняет атрибут цвета элемента, к которому он применяется, на красный. Это код для директивы color:

constructor(private el: ElementRef) {}

  ngAfterViewInit(): void {
    this.el.nativeElement.style.color = 'red'
  }

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

constructor(private el: ElementRef, private ren: Renderer2) { }

  ngAfterViewInit(): void {
    this.ren.removeAttribute(this.el.nativeElement, 'appColor');
  }

Идея в том, что я может просто удалить директиву из элемента, прежде чем он будет представлен. После печати el.nativeElement после удаления атрибута appColor выглядит, что атрибут пропал, но цвет уже был изменен на красный. В идеале директива для удаления должна срабатывать раньше, чем директива color, но я не могу понять, как Angular выбирает порядок.

Я даже пытался использовать структурную директиву, чтобы позаботиться об этом:

constructor(private vc: ViewContainerRef, private template: TemplateRef<any>, private ren: Renderer2) { }

  ngOnInit() {
    this.ren.removeAttribute(this.template.elementRef.nativeElement, 'appColor');
    this.vc.createEmbeddedView(this.template);
  }

но на самом деле это выдает ошибку о том, что el.removeAttribute не является функцией?

Существует ли установленный шаблон, который будет использоваться для использования директивы для удаления или остановки другой директивы на том же элементе для запуска ? Если нет, есть ли способ сделать это на самом деле?

Ответы [ 2 ]

0 голосов
/ 23 марта 2020

Насколько я знаю, вы не можете удалить директиву условно. Вместо этого вы можете иметь две версии элемента, одну с директивой, а другую без нее, и выбрать соответствующий элемент с помощью *ngIf... else. Чтобы не повторять внутреннее содержимое элементов, объявите это содержимое в общем шаблоне, который затем вставляется с ngTemplateOutlet.

<!-- Container element with the appColor directive -->
<p *ngIf="useColorDirective; else noColorDirective" appColor>
  <ng-container *ngTemplateOutlet="content"></ng-container>
</p>

<!-- Alternate container element, without the directive -->
<ng-template #noColorDirective>
  <p><ng-container *ngTemplateOutlet="content"></ng-container></p>
</ng-template>

<!-- Common content of the container elements -->
<ng-template #content>
  The inner content is here...
</ng-template>

. См. this stackblitz для демонстрации.

Если вы хотите использовать эту технику в нескольких местах, вы можете заключить код в компонент:

@Component({
  selector: 'app-p',
  ...
})
export class AppParagraphComponent {
  @Input() useColor = true;
}
<p *ngIf="useColor; else noColorDirective" appColor>
  <ng-container *ngTemplateOutlet="content"></ng-container>
</p>
<ng-template #noColorDirective>
  <p><ng-container *ngTemplateOutlet="content"></ng-container></p>
</ng-template>
<ng-template #content>
  <ng-content></ng-content>
</ng-template>

, который затем можно использовать как:

<app-p [useColor]="useColorDirective">
  This is the content!!!
</app-p>

См. этот стек для демонстрации. Возможно, вам потребуется определить отдельный компонент для каждого типа элемента, к которому можно условно применить директиву цвета.

0 голосов
/ 23 марта 2020

В Angular вы не можете динамически создавать / удалять директивы, несмотря ни на что ( Github Issue ). Если это импортированная библиотека, вам нужно ее разветвить и сделать, например, @Input() disabled с этой директивой, поэтому, когда она активна, она не будет запускать события (конечно, вам также нужно сделать эту логику c).

...