Search code examples
angularprimengfullscreen

Angular: this.confirmPosition is not a function


I'm trying to detect when user exits full screen with for example with esc button, I need to make a popup dialog when user exits the full screen mode

here's the code:

ngOnInit(): void {
  const document = window.document;
  if (document.addEventListener)
  {
   document.addEventListener('fullscreenchange',this.exitHandler, false);
   document.addEventListener('mozfullscreenchange',this.exitHandler, false);
   document.addEventListener('MSFullscreenChange',this.exitHandler, false);
   document.addEventListener('webkitfullscreenchange',this.exitHandler, false);
  }
}

exitHandler(){
     const document:any = window.document;
    if (document.webkitIsFullScreen === false){
      this.confirmPosition();
    }else if (document.mozFullScreen === false){
     this.confirmPosition();
    }else if (document.msFullscreenElement === false){
     this.confirmPosition();
    }
   }
  confirmPosition() {
    this.confirmationService.confirm({
        message: 'Do you want to delete this record?',
        header: 'Delete Confirmation',
        icon: 'pi pi-info-circle',
        accept: () => {
           
        },
        reject: () => {
           
        },
        key: "positionDialog"
    });
  }

But I'm getting this error and I don't know why while it's really a function?:

ERROR TypeError: this.confirmPosition is not a function

Note: I'm using primeng dialouge but this ofcourse doesn't matter about the content inside confirmPosition because if I changed the content to be like this :

confirmPosition() {
        console.log('hello ');
}

it still complain about the same error.


Solution

  • You need to bind this.

    document.addEventListener('fullscreenchange',this.exitHandler.bind(this), false);
    

    Explanation:

    In js, when calling function, inside the body of that function, when executing, this pointer will be an object that called that function. In this case, document object is calling that callback that you provided when you registered an event listener. If you want to change that, you can explicitly bind an object to a function with fnc1.bind(object)

    However, arrow functions in js are automatically bounded to lexical scope.

    Try this example below and watch console, you will realise what is happening

    import { Component, OnInit, VERSION } from "@angular/core";
    
    @Component({
      selector: "my-app",
      templateUrl: "./app.component.html",
      styleUrls: ["./app.component.css"]
    })
    export class AppComponent implements OnInit {
      ngOnInit() {
        // Here, this "pointer"inside the function body will be document object (since document object called it)
        document.addEventListener("click", function() {
          console.log("Inline function", this);
        });
    
        // Here, it will be the same as in prevoius case
        document.addEventListener("click", this.externalFunction);
    
        // Here, we will bind this pointer explicitly to a specific object (in this caase its AppComponent instance)
        document.addEventListener("click", this.externalFunctionWithBind.bind(this));
    
        // Arrow function will automatically bind this to an object that is in the lexical scope
        // Lexical scope is the one that is arounding it and it this case its AppComponent instance
        document.addEventListener("click", () => {
          console.log("Arrow function", this);
        });
      }
    
      inlineFunction() {
        console.log("Inline Function", this);
      }
    
    
      externalFunction() {
        console.log("External Function", this);
      }
    
        externalFunctionWithBind() {
        console.log("External Function With Bind", this);
      }
    }