Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Referencing viewChild queries within @defer blocks

by Laurence Ininda on January 28, 2026

A Primer on @defer

Angular's @defer allows developers to delay when a component will be initialized within a component's template, until a certain condition is met. This could be, when the content enters the viewport, or a user interacts with a specific element, e.t.c.

In our case, we utilize Angular Material Tabs with two tabs displaying two pieces of data:

<mat-tab-group [(selectedIndex)]="tabIndex">
    <mat-tab label="All Posts">
        <all-posts/>
    </mat-tab>
    <mat-tab label="Gallery">
        <gallery-view/>
    </mat-tab>
</mat-tab-group>

Our <gallery-view/> component may contain data that we don't want to load immediately until we click on that tab. We can wrap it within a @defer block to only initialize the component when it enters the viewport:

<mat-tab-group [(selectedIndex)]="tabIndex">
    <mat-tab label="All Posts">
        <all-posts/>
    </mat-tab>
    <mat-tab label="Gallery">
        @defer(on viewport) {
            <gallery-view/>
        } 
    </mat-tab>
</mat-tab-group>

Referencing content within @defer blocks

If we would like to reference our <gallery-view/>component that contains a property photoCount() (GalleryViewComponent.photoCount) and use that reference within the same template, we cannot directly use a template reference variable as such:

@if(tabIndex === 1) {
    <div>{{ galleryViewRef.photoCount() }} photos</div>
Will throw error: Property 'photoCount' does not exist on type 'undefined'.
}
 
<mat-tab-group [(selectedIndex)]="tabIndex">
    <mat-tab label="All Posts">
        <all-posts/>
    </mat-tab>
    <mat-tab label="Gallery">
        @defer(on viewport) {
            <gallery-view #galleryViewRef/>
        }
    </mat-tab>
</mat-tab-group>

To properly reference the <gallery-view/> component, we'll utilize the viewChild in the component's typescript file:

@Component({
    template: `
        @if(tabIndex === 1) {
            <div>{{ galleryComponent()?.photoCount() }} photos</div>
        }
 
        <mat-tab-group [(selectedIndex)]="tabIndex">
            <mat-tab label="All Posts">
                <all-posts/>
            </mat-tab>
            <mat-tab label="Gallery">
                @defer(on viewport) {
                    <gallery-view #galleryViewRef/> 
                }
            </mat-tab>
        </mat-tab-group>
    `
})
export class HomeComponent {
    galleryComponent = viewChild('galleryViewRef');
    tabIndex = 0;
}

Since viewChild keeps its result up to date as the application state changes, the variable galleryComponent is initially undefined until it inters the viewport.