user1532043 user1532043 - 4 days ago 6
AngularJS Question

Angular2 - How to access a child input element which is yet to be rendered?

For example, my template looks like -

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


And this is how my compoent looks like:

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();
}
}


In this case the focus doesn't work because the input element is still yet to be render. I realize that using timeout on that line will work, but somehow I don't feel like it's a good way to do it.

I guess somehow I have detect the change inside the parent div, and on that event I should do the focus operation. How would I do that? I feel like QueryList can be helpful but I can't figure out how do I use it in this case!!

Answer

This could work

@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

Comments