Skip to main content
Practice Problems

ViewChild and ContentChild in Angular

ViewChild and ContentChild

@ViewChild and @ContentChild are decorators that give you programmatic access to child elements, components, or directives in your template.


@ViewChild — Access Template Elements

Access elements defined in the component's own template:

typescript
@Component({ template: \` <input #nameInput type="text"> <app-chart #chart [data]="chartData"></app-chart> <button (click)="focusInput()">Focus</button> \` }) export class MyComponent implements AfterViewInit { @ViewChild('nameInput') inputEl!: ElementRef<HTMLInputElement>; @ViewChild('chart') chartComponent!: ChartComponent; ngAfterViewInit() { // Available after view init this.inputEl.nativeElement.focus(); this.chartComponent.refresh(); } focusInput() { this.inputEl.nativeElement.focus(); } }

@ViewChildren — Multiple Elements

typescript
@Component({ template: \` <app-tab *ngFor="let tab of tabs" [title]="tab.title"> {{ tab.content }} </app-tab> \` }) export class TabsComponent implements AfterViewInit { @ViewChildren(TabComponent) tabComponents!: QueryList<TabComponent>; ngAfterViewInit() { this.tabComponents.forEach(tab => console.log(tab.title)); // React to changes (when *ngFor adds/removes items) this.tabComponents.changes.subscribe(tabs => { console.log('Tabs changed:', tabs.length); }); } }

@ContentChild — Access Projected Content

Access elements projected into the component via <ng-content>:

typescript
@Component({ selector: 'app-panel', template: \` <div class="panel"> <ng-content></ng-content> </div> \` }) export class PanelComponent implements AfterContentInit { @ContentChild('panelTitle') titleEl!: ElementRef; @ContentChild(ButtonComponent) button!: ButtonComponent; ngAfterContentInit() { // Available after content init console.log(this.titleEl?.nativeElement.textContent); } }
html
<!-- Parent template --> <app-panel> <h2 #panelTitle>My Panel</h2> <app-button>Click me</app-button> </app-panel>

ViewChild vs ContentChild

Feature@ViewChild@ContentChild
AccessesComponent's own templateProjected content (ng-content)
LifecyclengAfterViewInitngAfterContentInit
Multiple@ViewChildren@ContentChildren
Defined inThe component's templateParent's template (projected)

Signal Queries (Angular 17+)

typescript
@Component({ /* ... */ }) export class MyComponent { // Signal-based queries (modern) nameInput = viewChild.required<ElementRef>('nameInput'); chart = viewChild(ChartComponent); tabs = viewChildren(TabComponent); // Content queries title = contentChild<ElementRef>('title'); buttons = contentChildren(ButtonComponent); }

Read Option

typescript
// Read as ElementRef instead of component instance @ViewChild('myComp', { read: ElementRef }) el!: ElementRef; // Read the ViewContainerRef (for dynamic components) @ViewChild('container', { read: ViewContainerRef }) container!: ViewContainerRef;

Important:

@ViewChild accesses elements in the component's own template (available in ngAfterViewInit). @ContentChild accesses projected content (available in ngAfterContentInit). In Angular 17+, prefer signal-based queries (viewChild(), contentChild()). Use QueryList.changes to react to dynamic content changes.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.

Finished reading?
Practice Problems