0

I have implemented a html5 minigame into an iframe in an angular app, but receiving data from it has been a hassle. I thought I got it working with an eventlistener, but now it makes one on opening the page, but doesn't remove it upon closing the page. So now reopening the page leaves multiple event listeners in place.

Since I want the data from the event, and I want to use other functions from the same class, I have implemented it like this

ngOnInit(){
window.addEventListener('message', (event) =>{
//do some stuff
this.someMethodINeed();
}

}

but now I cant remove this listener because the function is anonymous. I would like to have it implemented like this:

ngOnInit(){
window.addEventListener('message', this.handleEvent);
}

public handleEvent(event){
//do some stuff
this.someMethodINeed();
}

public navigate(path: string){
window.removeEventListener('message', this.handleEvent);
//navigate logic
}

but now it complains about 'this' being undefined, because that isn't in scope anymore when executed via a eventlistener.

Does someone know a way to either remove an anonymous eventlistener, or give an eventlistener a function while it can still call methods within the same class?

Thanks in advance, I have really been breaking my head on this for the past few hours.

EDIT raw code as requested

@Component({
  selector: 'seed-minigames',
  templateUrl: './minigames.component.html',
  styleUrls: ['./minigames.component.scss']
})
export class MinigamesComponent implements OnInit {
  constructor(public navigationService: NavigationService, public router: Router, private minigamesService: MinigamesService) {
}

  ngOnInit() {    
      var minigameServerAdress = this.minigamesService.MinigameServerAdress();
      //makes url for specific user, which sends user id
      var url = this.minigamesService.makeUrl();
      //set the iframes source to that url
      document.getElementById('minigame-iframe').setAttribute( 'src', url);
        //adding listener which listens for scores from the minigame, after the minigame page has been opened
        window.addEventListener('message', (event) => {
            //check the origin of the data
            if (~event.origin.indexOf(minigameServerAdress)) {
                //navigate to the homepage if the game is closed
                if(event.data == "exit"){
                    this.navigate(' ')
                }
                //otherwise procces the data as scores.
                else{
                    this.minigamesService.sendScores(event.data);
                }

            } else { 
                //the source wasnt confirmed, the data wasnt from our server, so we wont use this data.
                console.log("cant confirm source: "+ event.origin);
                return; 
            }
        }); 
  }

      // Navigate to a specific path.
      public navigate(path: string) {
        //this should remove the event listener, but im not sure how yet.
        // Navigate to 'path'
        this.router.navigate([path]);
    }
}
Matthias
  • 13,607
  • 9
  • 44
  • 60

1 Answers1

0

You can't do it with an anonymous function. You have to have a reference to the listener function.

Regarding your issues with having this undefined -- this is a common problem in JS and it's worth googling a bit. You can either use bind and store the result in a variable, or use arrow functions if you have them.

Matthias
  • 13,607
  • 9
  • 44
  • 60
  • 1
    thanks, after strugling a bit with where to put it, i fixed it with a fairly simple: ```this.handleEvent = this.handleEvent.bind(this);``` – Thomas Boddeus Apr 16 '19 at 09:03