【问题标题】:is there an Angular event like ngDoneCheck?是否有像 ngDoneCheck 这样的 Angular 事件?
【发布时间】:2019-12-06 15:43:15
【问题描述】:

问题

我想知道当一个新元素被添加到它正在动态跟踪的数组中时,Angular 已经完成渲染 *ngFor 指令(编辑:),并且在 ngAfterViewInit 之后。

示例

我的问题的一个例子:我有一个包含 2 个东西的数组。使用 ngFor 将它们生成为内容可编辑的 p 标签。

import { Component } from '@angular/core';
@Component({
  selector: 'app-root',
  template: `
    <p 
      *ngFor="let el of myArray" 
       contenteditable="true"
       (keydown.enter)="addNewP()"
    >{{el}}</p>
`,
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  myArray = ["first", "second"];
  addNewP(){
    this.myArray.splice(1, 0, "in the middle");
  }
}

如何在用户按下回车后获得 angular 已完成渲染的异步通知,以便我可以将焦点放在“中间”元素上?

我目前的解决方案

目前我正在使用来自https://www.codementor.io/yomateo/auto-focus-with-angular-7-the-directive-osfcl7rrv 的自定义指令:

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

@Directive({
  selector: '[appFocusNew]'
})
export class FocusNewDirective implements AfterContentInit{

  constructor(private el: ElementRef//tiny side note: angular warns extensively against this, should i avoid it?
    ) { }

  public ngAfterContentInit() {
    setTimeout(() => {
      this.el.nativeElement.focus();
    },0)
  }
}

【问题讨论】:

    标签: angular


    【解决方案1】:

    可以使用*ngFor提供的last值来完成

    <div *ngFor="let item of arr; let lastReached = last">
        <div>{{ last ? myFunction() }}</div>
    </div>
    

    【讨论】:

    • 拍摄,如果元素在数组的中间,这不起作用,它总是解析到最低的 p 元素
    • 问题是知道 for 循环已经停止渲染,那将是 lop 到达终点的时候。所以我们不需要检查数组的中间元素。
    • 哦,哇,是的,你是对的,我在想如果调用 addNewP() 方法,角度不会调用这个函数,因为最后一个元素不会被重新渲染,但是这个由于某种原因调用了函数,我不太明白。谢谢!!!
    【解决方案2】:
    import { Component, ViewChildren, QueryList, ElementRef, AfterViewInit } from "@angular/core";
    @Component({
      selector: "app-root",
      template: `
        <p
          #pList
          *ngFor="let el of myArray"
          contenteditable="true"
          (keydown.enter)="addNewP()"
        >
          {{ el }}
        </p>
      `,
      styleUrls: ["./app.component.css"]
    })
    export class AppComponent implements AfterViewInit {
      @ViewChildren("pList") protected pList: QueryList<ElementRef>;
    
      myArray = ["first", "second"];
      addNewP() {
        this.myArray.splice(1, 0, "in the middle");
      }
      ngAfterViewInit() {
        this.pList.first.nativeElement.focus();
      }
    }
    
    
    

    【讨论】:

    【解决方案3】:

    您可以在指令中使用OnInit 生命周期挂钩。还要确保在模板中使用类似appFocusNew = "" 的指令。否则ngOnInit 可能不会被解雇。

    指令:

    import { Directive, ElementRef, OnInit } from '@angular/core';
    
    @Directive({
      selector: '[appFocusNew]'
    })
    export class FocusNewDirective implements OnInit {
    
      constructor(private el: ElementRef) { }
    
      ngOnInit() {
        this.el.nativeElement.focus();
      }
    
    }
    

    模板:

    <p 
      *ngFor="let el of myArray" 
        contenteditable="true"
        (keydown.enter)="addNewP()"
        appFocusNew = ""> 
        {{el}}
    </p> 
    

    工作DEMO here.

    【讨论】:

      【解决方案4】:

      您可以在组件link 中使用 ngAfterViewChecked。每次检查您的 html 更改时都会调用它。

      这样,一旦你的数组被修改并且你的 html 发生了变化,ngAfterViewChecked 就会被调用,你就可以应用焦点了。

           export class AppComponent implements AfterViewChecked{
            myArray = ["first", "second"];
            ngAfterViewChecked(){
             // put focus here.
            }
          }
      

      【讨论】:

      • AfterViewInit 在按下回车键时无法工作,这会向 Angular 构建模板的数组添加一个新元素
      • 对不起,我错过了您在数组中添加新元素,请改用 ngAfterViewChecked。修改我的答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-29
      • 2017-10-20
      • 1970-01-01
      相关资源
      最近更新 更多