Consider this Angular component code snippet:
import { Component, ViewChild, ElementRef, AfterViewInit } from '@angular/core';
@Component({
selector: 'app-sample',
template: `<input #inputRef type='text' value='Hello' />`
})
export class SampleComponent implements AfterViewInit {
@ViewChild('inputRef') inputElement!: ElementRef;
ngAfterViewInit() {
console.log(this.inputElement.nativeElement.value);
}
} What will be logged to the console when this component renders?
import { Component, ViewChild, ElementRef, AfterViewInit } from '@angular/core'; @Component({ selector: 'app-sample', template: `<input #inputRef type='text' value='Hello' />` }) export class SampleComponent implements AfterViewInit { @ViewChild('inputRef') inputElement!: ElementRef<HTMLInputElement>; ngAfterViewInit() { console.log(this.inputElement.nativeElement.value); } }
Remember when @ViewChild references are available in the component lifecycle.
The @ViewChild decorator gets a reference to the input element after the view initializes. The value property of the native input element is 'Hello', so it logs "Hello".
Given a child component named ChildComponent, which @ViewChild declaration correctly gets its instance?
import { Component, ViewChild } from '@angular/core'; import { ChildComponent } from './child.component'; @Component({ selector: 'app-parent', template: `<child-component></child-component>` }) export class ParentComponent { // Which @ViewChild is correct? }
When querying by component class, you pass the class itself, not a string.
To get a child component instance by its class, you pass the class type to @ViewChild, like @ViewChild(ChildComponent). Using a string looks for a template reference variable, which is not present here.
In which lifecycle hook is the @ViewChild property guaranteed to be initialized and safe to use?
Think about when the component's view is fully rendered.
@ViewChild references are set after Angular initializes the component's view. This happens in the ngAfterViewInit() lifecycle hook. Before this, the reference may be undefined.
Examine this Angular component code:
import { Component, ViewChild, ElementRef } from '@angular/core';
@Component({
selector: 'app-debug',
template: `Content`
})
export class DebugComponent {
@ViewChild('myDiv') myDiv!: ElementRef;
ngOnInit() {
console.log(this.myDiv.nativeElement.textContent);
}
}What error will occur and why?
import { Component, ViewChild, ElementRef } from '@angular/core'; @Component({ selector: 'app-debug', template: `<div #myDiv>Content</div>` }) export class DebugComponent { @ViewChild('myDiv') myDiv!: ElementRef; ngOnInit() { console.log(this.myDiv.nativeElement.textContent); } }
Consider when @ViewChild properties are initialized relative to lifecycle hooks.
The @ViewChild property is not yet initialized in ngOnInit, so accessing this.myDiv.nativeElement causes a runtime error because myDiv is undefined at that point.
Given this Angular component:
import { Component, ViewChild, ElementRef, AfterViewInit } from '@angular/core';
@Component({
selector: 'app-expert',
template: ``
})
export class ExpertComponent implements AfterViewInit {
@ViewChild('inputRef') inputElement!: ElementRef;
ngAfterViewInit() {
this.inputElement.nativeElement.value = 'Changed';
}
changeValue() {
this.inputElement.nativeElement.value = 'Clicked';
}
} If the user clicks a button that calls changeValue() after the view loads, what is the input's value?
import { Component, ViewChild, ElementRef, AfterViewInit } from '@angular/core'; @Component({ selector: 'app-expert', template: `<input #inputRef type='text' value='Start' />` }) export class ExpertComponent implements AfterViewInit { @ViewChild('inputRef') inputElement!: ElementRef<HTMLInputElement>; ngAfterViewInit() { this.inputElement.nativeElement.value = 'Changed'; } changeValue() { this.inputElement.nativeElement.value = 'Clicked'; } }
Think about the order of operations: initial value, lifecycle hook, and user interaction.
The input starts with value 'Start'. After the view initializes, ngAfterViewInit sets it to 'Changed'. When the user clicks the button, changeValue() sets it to 'Clicked'. So the final value is 'Clicked'.