Stack Overflow
Stack Overflow

Reputation: 2764

Cannot read property 'native-element' of undefined Angular 8

after my angular application versions upgrade from angular 7 to angular 8 i run into a complication problem with rows like this

export class followupComponent implements OnInit {
    @ViewChild('message') messageElement: ElementRef;

    constructor(){}
    ...
}

I read that the new definition required static parameter and change the code

@ViewChild('message', { static: true })) messageElement: ElementRef;

and I thought that the problem had resolved.

But no, i accept run time error:

cannot read property 'nativeElement' of undefined

related to this code

HTML:

<div class="message">
    <div class="action-buttons">
        <img src="{{imgPath + '_Edit_Hover.png'}}" (click)="OnEdit(Followup)">
    </div>
    <textarea matInput #message [ngModel]="Followup.Message"></textarea>
</div>

TS:

OnEdit(followup: Followup) {
    setTimeout(() => this.messageElement.nativeElement.focus());
}

What is the correct definition of ElementRef in angular 8,

or - How to resolve this problem?

Upvotes: 11

Views: 39761

Answers (2)

ysf
ysf

Reputation: 4844

<textarea matInput #message [ngModel]="Followup.Message"></textarea> this piece of code probably needs some logic to get displayed (such as *ngIf or *ngFor on parent nodes, or some asynchronous code) which means that one changedetection cycle is required for it to get displayed.

According to Angular 8 docs

static - whether or not to resolve query results before change detection runs (i.e. return static results only). If this option is not provided, the compiler will fall back to its default behavior, which is to use query results to determine the timing of query resolution. If any query results are inside a nested view (e.g. *ngIf), the query will be resolved after change detection runs. Otherwise, it will be resolved before change detection runs.

so you should set static to false

@ViewChild('message', { static: false })) messageElement: ElementRef;

here is a simple demo https://stackblitz.com/edit/angular-qgwhcv

in the demo above, input box gets displayed after 3 seconds. if you set static:false and click edit after input gets displayed it successfully focuses the input. but if you change static:true and click edit after input gets displayed, you will see error in the console.

Upvotes: 17

DevLoverUmar
DevLoverUmar

Reputation: 13923

I was facing the same problem because of creating an ElementRef type ChildView for a mat-option element like this

Template

<mat-select (selectionChange)="handleMetaSignalChange();">
<mat-option #metaSignalOption *ngFor="let metaSignal of metaSignals" [value]="metaSignal">
                                {{ metaSignal.name }}
</mat-option>
</mat-select>

Code

 @ViewChild("metaSignalOption", { static: false }) selectedMetaSignal : ElementRef;

 handleMetaSignalChange() {
   console.log('Meta Signal Changed to ' + this.selectedMetaSignal.nativeElement.value);
 }

And I fixed the issue using MatOption instead of ElementRef because ElementRef works only for native DOM elements as per official docs.

Updated Code

  @ViewChild("metaSignalOption", { static: false }) selectedMetaSignal : MatOption;

  handleMetaSignalChange() {
   // Now selectedMetaSignal is a MatOption, not a native Element
    console.log('Meta Signal Changed to ' + this.selectedMetaSignal.viewValue);
  }

Upvotes: 2

Related Questions