4

I really an imported 3rd party script to trigger a function like show_end_screen (below)

my component

import { Router } from '@angular/router';
import { init_game, start_game, stop_game } from '../../assets/js/game';

@Component({})

export class PlayComponent implements OnInit {
    constructor(public router:Router) {}
    ngOnInit() {
        init_game(this.show_end_screen) // load ready
    }
    show_end_screen(data){
        console.log(data) //this works
        this.router.navigate(['play']); //"this" is undefined
    }
}

init_game(this.show_end_screen) <== Here I am passing show_end_screen to the imported script. when the 3rd party script runs show_end_screen(data) I successfully log data to the console. But i dont have access to this or any other reference to angular

this.router.navigate(['play']); <== here i get a console error

ERROR TypeError: Cannot read property 'nav' of undefined

Omar
  • 2,726
  • 2
  • 32
  • 65
  • Where do you define `router` in your component? – bugs Mar 29 '18 at 20:47
  • 3
    Possible duplicate of [How to access the correct \`this\` inside a callback?](https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback) – Estus Flask Mar 29 '18 at 21:02
  • This question is answered [here](https://stackoverflow.com/a/45136760/822947) – yanot Jul 04 '18 at 23:50
  • Possible duplicate of [How to properly do a "bind" in angular2 typescript?](https://stackoverflow.com/questions/45136680/how-to-properly-do-a-bind-in-angular2-typescript) – yanot Jul 04 '18 at 23:56

3 Answers3

6

When you pass a class-bound method as a value it loses the context (this). You can bind explicitly or call within the callback:

ngOnInit() {
  // explicit binding
  init_game(this.show_end_screen.bind(this));

  // lexical binding
  init_game(data => this.show_end_screen(data));
}

You can also use an instance-bound method for your component instead.

show_end_screen = (data) => {
  this.router.navigate(['play']);
}
Explosion Pills
  • 188,624
  • 52
  • 326
  • 405
  • so glad to have your help! `.bind(this)` ... will that change how the callback is used in the other script? – Omar Mar 29 '18 at 20:55
  • I dont understand how it works but It did... Need to study up... Thanks! – Omar Mar 29 '18 at 21:06
0

This is because this refers to the calling context, not the context from which you assign your callback. You should be able to make this work, by explicitly defining which context this refers to by using the bind function.

So your code would look like this:

ngOnInit() {
    init_game(this.show_end_screen.bind(this))
}
Nikolaj Dam Larsen
  • 5,455
  • 4
  • 32
  • 45
0

I'm assuming this.router is defined in your constructor

In addition to @Explossion Pills answer, you could define your method as a property and save that bind() call

show_end_screen = (data) => {
  console.log(data) //this works
  this.router.navigate(['play']); //"this" is undefined
}
lleon
  • 2,615
  • 1
  • 20
  • 14