一旦 ngIf 完成渲染 html 元素,如何在 ngIf 中触发指令?

How to trigger a directive within ngIf once ngIf finishes rendering html elements?

我的问题涉及 *ngif 指令,一次 *ngif=true 我希望 html 内容在我的 'ModClass' 指令执行它的操作之前先呈现。

我尝试实现 ngOnInit 和 ngViewInit 但没有成功,因为我相信 ngOnInit 在呈现 ngif 内容时触发,或者可能在生成父组件时触发。

还有 ngViewInit,我想我需要订阅一些东西,但我不知道我需要订阅什么。 (我可能完全错了这将做更多的研究)

以下代码说明了我的问题以及 stacksblitz link,因此您无需在计算机上重新创建此代码即可进行故障排除。

代码应该做的是点击按钮,它切换一个与 ngIf 一起使用的布尔变量:*ngIf='trigger'

ngIf 代码将显示默认为 css class 'red' 的 div 块,但我的指令会将其更改为 'blue' class.

更新

事实证明,只要我使用 ElementRef,ngViewInit 就可以正常工作。 感谢大家的帮助。

指令在src/app/modify-class/modify-class.指令

import { Directive, OnInit } from '@angular/core'

@Directive({
  selector: 'ModClass'
})
export class ModifyClassDirective implements OnInit {

  constructor (private htmlElement: HTMLElement) {}

  //should i try ngViewinit instead
  ngOnInit () {
    this.activateThisClass()
  }

  /*ngViewInit () {
    this.activateThisClass()
  }*/
  //this function should execute once ng-if condition is true and html is rendered
  activateThisClass () {
    console.log('i\'ve been triggered')
    const list = this.htmlElement.getElementsByClassName('red')
    list.forEach(element => element.classList.remove('red'))
    list.forEach(element => element.classList.add('blue'))
  }
}

HTML/Hello 在 src/app/hello.component

中找到的组件内容
import { Component, Input } from '@angular/core';

@Component({
  selector: 'hello',
  template: `
<h1>Hello {{name}}!</h1>
  <button ModClass='' (click)="trigger=!trigger;"> click me </button>

<div *ngIf='trigger'> 

  <!-- This is what i want to change once it is rendered -->
  <div ModClass='' class='red'> this will/should be overwritten and turn blue </div>

</div>`,
  styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent  {
  @Input() name: string;
  @Input() trigger: boolean;

  constructor() {this.trigger = false}
}

linkt 到 Stackblitz Link

我不知道你是否打算使用问题中描述的指令(因为 red class 似乎仅在元素不存在时才应用)但在这里您可以更改两件事以使其正常工作:

  • 将指令 selectorModClass 更改为 [ModClass]
  • 在指令构造函数中注入 ElementRef 而不是 HTMLElement

修改后的代码如下:

import { Directive, ElementRef, OnInit } from '@angular/core'

@Directive({
  selector: '[ModClass]'
})
export class ModifyClassDirective implements OnInit {

  constructor (private elementRef: ElementRef) {}

  ngOnInit () {
    this.activateThisClass()
  }

  activateThisClass () {
    console.log("activateThisClass triggered!")
    const element = this.elementRef.nativeElement;
    element.classList.remove('red');
    element.classList.add('blue');
  }
}

参见 the modified stackblitz

我对你的代码做了一些修改:

<button (click)="trigger=!trigger;"> click me </button>

<div *ngIf='trigger'> 
  <!-- This is what i want to change once it is rendered -->
  <div ModClass class='red'> this will/should be overwritten and turn blue </div>

你的指令应该是这样的:

import { Directive, OnInit } from '@angular/core'
import { ElementRef } from '@angular/core';
@Directive({
  selector: '[ModClass]' // changed
})
export class ModifyClassDirective implements OnInit {
  constructor (private el: ElementRef) {}
  ngOnInit () {
    this.activateThisClass()
  }
  activateThisClass () {
    this.el.nativeElement.style.backgroundColor = "blue";
  }
}

有关自定义指令的更多详细信息,请查看此 link :Custome directive

您也可以在 ngAfterViewInit 中执行相同的操作。