Angular2 - 如何访问尚未呈现的子输入元素?

时间:2016-12-01 12:06:12

标签: angular

例如,我的模板看起来像 -

<div #parent>
    <button (click)="showInput()"> Show </button>
    <input #inp *ngIf="showInpField" />
</div>

这就是我的组件的样子:

import { Component, OnInit, ViewChild } from '@angular/core';
@Component({
  selector: 'some-component',
  templateUrl: './template.html',
})
export class SomeComponent {
    @ViewChild('inp') inpField: any;
    showInpField = false;
    constructor() {}
    showInput(){
        this.showInpField = true;
        // This doesn't work
        this.qaTitle.inpField.focus();
    }   
}

在这种情况下,焦点不起作用,因为输入元素仍然需要渲染。我意识到在该行上使用超时会起作用,但不知怎的,我觉得这不是一个很好的方法。

我想不知怎的,我已经检测到父div中的变化,并且在那个事件上我应该进行焦点操作。我该怎么办?我觉得QueryList可能会有所帮助,但在这种情况下我无法弄清楚如何使用它!

2 个答案:

答案 0 :(得分:3)

这可行吗

@Component({
  selector: 'my-app',
  template: `
    <div>
      <button (click)="toggleInput()"> {{ showInpField ? 'Hide' : 'Show'}} </button>
      <input #inp *ngIf="showInpField" />
  </div>
  `
})
export class AppComponent { 
  @ViewChildren('inp', { read: ElementRef }) elemRefs: QueryList<ElementRef>;

  showInpField = false;

  constructor(private renderer: Renderer){}

  toggleInput(){
    this.showInpField = !this.showInpField;
  }  

  ngAfterViewInit() {
    this.elemRefs.changes.subscribe(item => {
      if(!this.elemRefs.length) return;

      this.renderer.invokeElementMethod(this.elemRefs.first.nativeElement, 'focus');
    })
  } 
}

<强> Plunker Example

答案 1 :(得分:3)

官方方式是使用Renderer

https://angular.io/docs/ts/latest/api/core/index/Renderer-class.html

import {Component, NgModule, Renderer, ViewChild} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2 (click)="toggleInput()">Hello {{name}}</h2>
      <input value="any other input.." />
      <br />
      <input #inpt *ngIf="showInput" />
    </div>
  `,
})
export class App {
  @ViewChild('inpt') input;
  name:string;
  showInput = false;

  constructor(private _renderer: Renderer) {
    this.name = 'Angular2'
  }

  private toggleInput() {
    this.showInput = !this.showInput;

    if (this.showInput) {
      setTimeout(() => {
        this._renderer.invokeElementMethod(this.input.nativeElement, 'focus');
      }, 1);
    }
  }
}

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ App ],
  bootstrap: [ App ]
})
export class AppModule {}

现场演示:https://plnkr.co/edit/DWaEvqjFARRsKg1Byeu7?p=preview