Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly wait for the template to update in Angular 2

I'm trying to understand the best approach to wait for the template to update in an Angular 2 application after the model has changed.

@Component{
   template : `<button type="button" (click)="handleClick()">Click</button>
               <div *ngIf="!hidden">
                   <input type='text' #eleInput/>
               </div>`
}
export class Sample{
   private hidden: boolean = true;
   @ViewChild('eleInput') eleInput: ElementRef;

   constructor(){}

   handleClick(){
      this.hidden = false;

      //nativeElement is undefined here
      this.eleInput.nativeElement.focus();

      //nativeElement is defined here
      setTimeout(() => {
        this.eleInput.nativeElement.focus();
      });
   }
}

Using setTimeout in the above code seems hacky, so I'd like to know if there's a better approach.

Thanks!

like image 357
Christopher Avatar asked Oct 16 '16 16:10

Christopher


2 Answers

There is no way to wait for the template to update.

You can inject ChangeDetectorRef

constructor(private cdRef:ChangeDetectorRef) {}

and then call

this.cdRef.detectChanges();

As far as I know the template is updated when the call returns.

like image 131
Günter Zöchbauer Avatar answered Nov 03 '22 20:11

Günter Zöchbauer


Use [hidden] instead of ngIf. NgIf removes element. That's the reason this.eleInput.nativeElement.focus(); doesn't work without setTimeout because this.eleInput.nativeElement.focus(); line runs immediately before DOM element is/becomes set for the further reference.
When [hidden] property doesn't remove DOM element. It just shows and hides an element. So DOM element reference will be there and you nativeElement won't be undefined. So, it will work.

<div [hidden]="hidden">                        //<<<===use hidden instead of *ngIf
            <input type='text' #eleInput/>
</div>

private hidden: boolean = true;
   @ViewChild('eleInput') eleInput: ElementRef;

   constructor(){}

   handleClick(){
      this.hidden = false;                      
      this.eleInput.nativeElement.focus();     //<<<===now this will work.
   }
}
like image 6
Nikhil Shah Avatar answered Nov 03 '22 21:11

Nikhil Shah