【问题标题】:How to trigger a directive within ngIf once ngIf finishes rendering html elements?一旦 ngIf 完成呈现 html 元素,如何在 ngIf 中触发指令?
【发布时间】:2019-03-21 11:06:20
【问题描述】:

我的问题涉及 *ngif 指令,一旦 *ngif=true 我希望 html 内容先呈现,然后我的“ModClass”指令可以执行它的工作。

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

对于 ngViewInit,我认为我需要订阅一些东西,但我不知道我需要订阅什么。 (我可能完全错了这会做更多的研究)

以下代码说明了我的问题以及 stacksblitz 链接,因此您不必在计算机上重新创建此代码来进行故障排除。

代码的作用是在按钮单击时切换与 ngIf 一起使用的布尔变量,如下所示:*ngIf='trigger'

ngIf 代码将显示一个带有默认 css 类“红色”的 div 块,但我的指令会将其更改为“蓝色”类。

更新

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

src/app/modify-class/modify-class.directive中的指令

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'))
  }
}

在 src/app/hello.component 中找到的 HTML/Hello 组件内容

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}
}

链接到Stackblitz Link

【问题讨论】:

    标签: angular angular-directive lifecycle angular-ng-if


    【解决方案1】:

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

    • 将指令 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

    【讨论】:

    • 我写的是我正在研究的简化版本,但是您对注入 ElementRef 的建议是我需要在 ngViewInit() 函数中使用的。谢谢。
    【解决方案2】:

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

    <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";
      }
    }
    

    有关自定义指令的更多详细信息,请访问此链接:Custome directive

    你也可以在 ngAfterViewInit 中做同样的事情。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-03-25
      • 2019-01-27
      • 1970-01-01
      • 1970-01-01
      • 2021-05-15
      • 2018-04-25
      • 2020-08-21
      相关资源
      最近更新 更多