The bottom line is: I have MainComponent , code :

 import {Component, OnInit, OnDestroy, ViewChild, AfterViewInit} from "@angular/core"; import {WebSocketService} from "../services/websocket.service"; import {ActivatedRoute} from '@angular/router'; import {Subscription} from "rxjs/Rx"; import {User} from "../../client/user.model"; import {NotificationComponent} from "../../notification/components/notification.component"; import {ToasterService, ToasterContainerComponent} from "angular2-toaster/angular2-toaster"; @Component({ selector: 'main', template: `<toaster-container></toaster-container> <notification-component></notification-component> <button (click)="popToast()">pop toast</button>`, providers: [WebSocketService, ToasterService], directives: [NotificationComponent, ToasterContainerComponent] }) export class MainComponent implements OnInit, OnDestroy, AfterViewInit { @ViewChild(NotificationComponent) private notification: NotificationComponent; private sub: Subscription; private user: User; private toasterService: ToasterService; constructor(private route: ActivatedRoute, private ws: WebSocketService, toasterService: ToasterService) { this.toasterService = toasterService; this.user = new User(); } popToast() { this.toasterService.pop('success', 'Args Title', 'Args Body'); this.notification.start({ timeout: 50, type: 'info', title: 'Test Web Service', body: 1, buttonCloseShow: false }); } ngOnInit() {} ngAfterViewInit() { this.sub = this.route .params .subscribe(params => { this.user.room = params['room']; this.user.name = params['name']; this.user.lastname = params['lastname']; }); this.init(); } init() { this.ws = new WebSocketService(); this.ws.run(this.onMessage); setTimeout(() => this.ws.send({ name: this.user.name, lastname: this.user.lastname, room: this.user.room, action: 'client_go_test' }), 500); } ngOnDestroy() { this.sub.unsubscribe(); } onMessage(event: MessageEvent) { let routes: Object = { 'go_test': (response) => { console.log(response) }, 'client_test_not_found': (response) => { //this.toasterService.pop('success', 'Args Title', 'Args Body'); console.log(this.notification); this.notification.start({ type: 'info', title: 'Test Web Service', body: response, buttonCloseShow: false }); } }; let data = JSON.parse(event.data); if (routes.hasOwnProperty(data.action)) { routes[data.action](data.response); } } } 

NotificationComponent code

 import {Component} from "@angular/core"; import {TimerService} from "../services/timer.service"; @Component({ selector: 'notification-component', template: `<div class="j-toast {{toastConfig.type}}" [ngStyle]="{'opacity': opacity}" (mouseenter)="onEnter()" (mouseleave)="onLeave()"> <div *ngIf="toastConfig.buttonCloseShow" class="toast-close" (click)="close()">X</div> <div id="toast-progress" class="toast-progress" [ngStyle]="{'width': timerService.getWidth() + '%'}"></div> <div class="toast-content"> <div class="toast-data"> <div class="toast-title">{{toastConfig.title}}</div> <div class="toast-body">{{toastConfig.body}}</div> </div> <div class="toast-icon"></div> </div> </div>`, providers: [TimerService] }) export class NotificationComponent { private opacity: number = 0; public toastConfig: Object = {}; constructor(public timerService: TimerService) {} public start(config: Object) { this.opacity = 1; this.toastConfig = config; this.timerService.start(this.toastConfig['timeout']); } public close() { this.opacity = 0; this.timerService.close(); } onEnter(): void { this.timerService.pause(); } onLeave(): void { this.timerService.resume(); } } 

when I call popToast by pressing the button, all toast work, but if I receive a message from the sockets (the problem is not in the sockets) and I call there

 this.notification.start({ type: 'info', title: 'Test Web Service', body: response, buttonCloseShow: false }); 

I get TypeError: Cannot read property 'start' of undefined

    1 answer 1

    This design:

     let x = new MyObject(); let y = x.printThing; y() 

    loses this context.

    This can be circumvented in two ways:

    When passing a class method as a callback function, create an additional closure:

     let y = () => x.printThing() 

    Or create this closure immediately instead of the class method:

     class MyObject{ private status = "blah"; public printThing = () => { // <-- alert(this.status); } } ... let x = new MyObject(); let y = x.printThing 
    • Typescript solves this problem, I even checked everything, too - jashka
    • and what is generally equal to this at the moment when a message comes from sockets? - Alexandr
    • Check out this article at github.com/Microsoft/TypeScript/wiki/… since the Red Flags for this . Your situation is very similar. Try to declare onMessage as shown below in the block Fixes - Alexandr
    • I understood what the salt is, onMessage, however, the callback of this websocket this points to it even as you suggested, how in this case to be? make the notification static? - jashka
    • @jashka see comment above - Alexandr