liwevire
liwevire

Reputation: 903

Could not able to access property of angular component inside it

Trying to show SSE events in a snack bar. Issue is I couldn't able to access the snackBar property inside onMessage function of EventSource. Error shown in the browser console is Cannot read property 'open' of undefined.

import {Component, OnInit} from '@angular/core';
import {MatSnackBar} from '@angular/material';
@Component({
  selector: 'snack-bar-overview-example',
  templateUrl: 'snack-bar-overview-example.html',
})
export class SnackBarOverviewExample implements OnInit{
  constructor(public snackBar: MatSnackBar) {}
  ngOnInit() {
     //Created a local Server Sent Events server
     //which sends timestamp for every 5 second
     var source = new EventSource('http://localhost:8000/events');
     source.onmessage = function(response){
       console.log('test', response.data);
       //Could not able to access snackbar
       //Error statement is given below
       //Cannot read property 'open' of undefined
       this.snackBar.open(response.data, 'close', {
         duration: 4000
       });
     }
     //Same lines here, have no issues and working perfectly
     this.snackBar.open('message', 'close', {
       duration: 4000
     });
  }
}

Upvotes: 0

Views: 2698

Answers (2)

Chris Sharp
Chris Sharp

Reputation: 1995

Since you're trying to access this in a callback then you are in the wrong scope to be able to. There are two ways to solve this. The first, and best, is to modify your existing function to use the fat arrow syntax:

 source.onmessage = (response) => {
   console.log('test', response.data);
   //Could not able to access snackbar
   //Error statement is given below
   //Cannot read property 'open' of undefined
   this.snackBar.open(response.data, 'close', {
     duration: 4000
   });
 }

The other, which works but hated by some, is to create a variable self when you enter your ngOnInit and use that to maintain a reference to the proper scope.

ngOnInit() {
     const self = this; // here is where you would create it
     //Created a local Server Sent Events server
     //which sends timestamp for every 5 second
     var source = new EventSource('http://localhost:8000/events');
     source.onmessage = function(response){
       console.log('test', response.data);
       //Could not able to access snackbar
       //Error statement is given below
       //Cannot read property 'open' of undefined
       // replace this with self here 
       self.snackBar.open(response.data, 'close', {
         duration: 4000
       });
     }
     //Same lines here, have no issues and working perfectly
     self.snackBar.open('message', 'close', {
       duration: 4000
     });
  }

The first is a better solution but either will do what you need.

Upvotes: 3

Amit Chigadani
Amit Chigadani

Reputation: 29715

Use fat arrow ()=> instead of function.

source.onmessage = (response) => {
       console.log('test', response.data);
       //Could not able to access snackbar
       //Error statement is given below
       //Cannot read property 'open' of undefined
       this.snackBar.open(response.data, 'close', {
         duration: 4000
       });
     }

this object cannot be accessed inside function block.

Upvotes: 2

Related Questions