一旦 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 似乎仅在元素不存在时才应用)但在这里您可以更改两件事以使其正常工作:
- 将指令 selector 从
ModClass
更改为 [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');
}
}
我对你的代码做了一些修改:
<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 中执行相同的操作。
我的问题涉及 *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 似乎仅在元素不存在时才应用)但在这里您可以更改两件事以使其正常工作:
- 将指令 selector 从
ModClass
更改为[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');
}
}
我对你的代码做了一些修改:
<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 中执行相同的操作。