nativeElement select等待绑定数据

时间:2019-01-18 13:55:15

标签: javascript angular

假设我有一个名为inputComponent的子组件,它具有一个如下的单个输入元素

@Component({ template: `<input #count [(ngModel)]="item.count" />`})
export class inputComponent implements OnInit {

    @Input item;
    @ViewChild("count") count : ElementRef ; 


    focus(){
       this.count.nativeElement.focus();
       this.count.nativeElement.select();
    }

 }

我将其包含在父容器中,如下所示

<app-input-component [item]="item" ></app-input-component>

我要实现的目的是选择某个事件的文本输入。 例如

@ViewChild("input") count : inputComponent ; 
foo(){
this.item = item ; 
this.count.focus();
}

问题是,当我在更改绑定数据(项目)后立即调用焦点更改时,如果我在短暂的超时后调用focus()时,它没有选择任何悬停功能,则效果很好。

我知道使用setTimeOut解决问题不是正确的方法。

Stackblitz网址

https://stackblitz.com/edit/angular-svgmtg

2 个答案:

答案 0 :(得分:0)

据我所知,您尝试在呈现元素之前先获取它。那是不可能的。 我建议您阅读有关Angular中的Lifecycle挂钩的信息。 https://angular.io/guide/lifecycle-hooks

您可以通过在生命周期挂钩-ngAfterViewInit中调用foo()函数来解决此问题。

ngAfterViewInit() {
   this.foo();
}

答案 1 :(得分:0)

显然,ngModel会在模型更改时异步更新视图的值。即<input>的值直到下一个更改检测周期才更改!

来自ngModel source code

/**
 * `ngModel` forces an additional change detection run when its inputs change:
 * E.g.:
 * ```
 * <div>{{myModel.valid}}</div>
 * <input [(ngModel)]="myValue" #myModel="ngModel">
 * ```
 * I.e. `ngModel` can export itself on the element and then be used in the template.
 * Normally, this would result in expressions before the `input` that use the exported directive
 * to have and old value as they have been
 * dirty checked before. As this is a very common case for `ngModel`, we added this second change
 * detection run.
 *
 * Notes:
 * - this is just one extra run no matter how many `ngModel` have been changed.
 * - this is a general problem when using `exportAs` for directives!
 */
const resolvedPromise = Promise.resolve(null);

然后,在更新模型时,视图为updated asynchronously

private _updateValue(value: any): void {
  resolvedPromise.then(
      () => { this.control.setValue(value, {emitViewToModelChange: false}); });
}

因此setTimeout确保在更新视图后选择了输入。

如果要避免这种异步行为,可以使用FormControl代替ngModelDemo StackBlitz):

import { Component, Input, ViewChild, ElementRef } from '@angular/core';
import { FormControl } from '@angular/forms';

@Component({
  selector: 'hello',
  template: `<input #input [formControl]="count" />`,
  styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent {
  private _item;

  @Input() set item(value) {
    this._item = value;
    this.count.setValue(value.count);
    this.focus();
  }

  get item() {
    return this._item;
  }

  @ViewChild('input') input: ElementRef;

  count = new FormControl();

  focus() {
    this.input.nativeElement.focus();
    this.input.nativeElement.select();
  }
}

使用这种方法,您无需从父组件中显式调用focus();输入更改时,子组件将调用其自己的focus方法。