angular tutorials

@ContentChild TypeError: Cannot read property ‘nativeElement’ of undefined

This tutorial guides you on how to resolve @ContentChild TypeError: : Cannot read property ‘nativeElement’ of undefined error that you are facing in Angular.

@ContentChild: Cannot read property ‘nativeElement’ of undefined

When I was trying access to ng-content with @ContentChild I got the following error : Cannot read property ‘nativeElement’ of undefined.

ERROR TypeError: Cannot read property 'nativeElement' of undefined
    at ItemElementComponent.push../src/app/item-element/item-element.component.ts.ItemElementComponent.ngOnInit (item-element.component.ts:54)
    at callHook (core.js:2970)
    at callHooks (core.js:2940)
    at executeInitAndCheckHooks (core.js:2892)
    at selectIndexInternal (core.js:6331)
    at ɵɵadvance (core.js:6304)
    at AppComponent_app_item_element_9_Template (template.html:31)
    at executeTemplate (core.js:7757)
    at refreshView (core.js:7626)
    at refreshEmbeddedViews (core.js:8726)

Here is the code that I tried accessing ng-content with @ContentChild which resulted in above error. In App Component placed the local reference “#contentParagraph” on the pragraph.

app.component.html

<div class="container">
  <app-create-item (itemAdded)="onItemAdded($event)"
                   (itemSpecAdded)="onItemSpecAdded($event)"></app-create-item>
  <hr>
  <div class="row">
    <div class="col-xs-12">
      <button class="btn btn-primary" (click)="onChangeComponentElement()">Change item element</button>
      <!-- To Demo ngOnDestroy() -->
      <button class="btn btn-danger" (click)="onDestroyComponentElement()"> Destroy component</button>
      <app-item-element *ngFor="let elem of itemElems"
                        [itemElem] = "elem"
                        [title] = "elem.title">
                        <!-- projecting content into component with ng-content -->
                        <p #contentParagraph>
                          <strong *ngIf="elem.type === 'item'" style="color: orange">{{ elem.desc }}</strong>
                          <em *ngIf="elem.type === 'spec'">{{ elem.spec }}</em>
                        </p>
      </app-item-element>

    </div>
  </div>
</div>

Then, accessed the template reference variable “#contentParagraph” in our ItemElementComponent class using @ContentChild as shown below.

item-element.component.ts

import { 
  AfterViewChecked,
  AfterViewInit,
  AfterContentChecked,
  AfterContentInit,
  Component, 
  DoCheck, 
  Input, 
  OnChanges, 
  OnInit, 
  SimpleChanges,
  OnDestroy,
  ElementRef,
  ContentChild
} from '@angular/core';

@Component({
  selector: 'app-item-element',
  templateUrl: './item-element.component.html',
  styleUrls: ['./item-element.component.css'],
  
})

export class ItemElementComponent implements OnInit, OnChanges, DoCheck, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked, OnDestroy{

  @Input() itemElem : {type: string, title: string, desc: string, spec: string};
  @Input() title : string;
  @ContentChild('contentParagraph') paragraph : ElementRef;
  
  constructor() {
    console.log("constructor called.....");
  }

  ngOnChanges(changes: SimpleChanges) {
    console.log("ngOnChanges called.....");
    console.log(changes);
  }

  ngOnInit(): void {
    console.log("ngOnInit called.....");
    console.log('Paragraph text Content:' + this.paragraph.nativeElement.textContent);
  }

  ngDoCheck(){
    console.log("ngDoCheck called.....");
  }

  ngAfterContentInit(){
    console.log("ngAfterContentInit called.....");
    
  }

  ngAfterContentChecked(){
    console.log("ngAfterContentChecked called.....");
  }

  ngAfterViewInit(){
    console.log("ngAfterViewInit called.....");
  }

  ngAfterViewChecked(){
    console.log("ngAfterViewChecked called.....");
  }

  ngOnDestroy(){
    console.log("ngOnDestroy called.....");
  }

}

While running Angular application with above code changes I got ERROR TypeError: Cannot read property ‘nativeElement’ of undefined.

After referring angular docs I understood that from Angular 8+, the @ContentChild syntax have been changed slightly as shown below.

Instead of:

@ContentChild('contentParagraph') paragraph: ElementRef;

Should use

@ContentChild('contentParagraph', {static: true}) paragraph: ElementRef;

Note, you need to add {static: true} as a second argument, if you are planning to access the selected element inside of ngOnInit(). And if you don’t access the selected element in ngOnInit(), but elsewhere in your component the set {static: false} instead.

Also, note if you are using Angular 9+, you need to add {static:true}  if needed, but not {static:false}

Of course, you can’t access the value “paragraph” of before you reach ngAfterContentInit() as shown below***.

item-element.component.ts:43 constructor called.....
item-element.component.ts:47 ngOnChanges called.....
item-element.component.ts:48 {itemElem: SimpleChange, title: SimpleChange}
item-element.component.ts:52 ngOnInit called.....
***item-element.component.ts:53 Header Content:
***item-element.component.ts:54 Paragraph text Content:
item-element.component.ts:58 ngDoCheck called.....
item-element.component.ts:62 ngAfterContentInit called.....
***item-element.component.ts:63 Paragraph text Content:Android phone by Google

Therefore, after adding second argument {static: true} , the error TypeError: : Cannot read property ‘nativeElement’ of undefined while using @ContentChild is gone away.

Hope it helped 🙂

References:

guest
1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Yerraguntla Bhaskar Reddy
Yerraguntla Bhaskar Reddy
4 months ago

you saved my whole day, it worked for me and hope for everyone.