0

I have a service with a member variable that is set by a method, and then referenced by another method in the same service.

I was wondering if I had multiple instances of the service, so the constructor ensures the service is not instantiated twice, and since no such error is thrown I understand the service is instantiated only once.

@Injectable({
  providedIn: 'root'
})
export class PwaService implements OnDestroy {

  private installPromptEvent?: Event;

  constructor(
    // Ensure the service is injected only once
    @Optional() @SkipSelf() pwaService: PwaService,
  ) {
    if (pwaService) {
      throw new Error('The PWA service has ALREADY been injected.');
    }
  }

  ngOnDestroy() {
    window.removeEventListener('beforeinstallprompt', this.handleBbeforeInstallAndroid);
  }

  private handleBbeforeInstallAndroid(event: Event): void {
    event.preventDefault();
    this.installPromptEvent = event;
    console.log(this.installPromptEvent);
  }

  private receivedInstallPromptEventAndroid(): boolean {
    console.log(this.installPromptEvent);
    console.log(this.installPromptEvent != null);
    return this.installPromptEvent != null;
  }

  private isInstallable(): boolean {
    if (this.platform.ANDROID) {
      return this.receivedInstallPromptEventAndroid() && !this.isInStandaloneModeAndroid();
    } else if (this.platform.IOS) {
      return this.isInStandaloneModeIOS();
    } else {
      return false;
    }
  }

  public checkForBeforeInstallEvents(): void {
    if (this.platform.ANDROID) {
      if (!this.isInStandaloneModeAndroid()) {
        window.addEventListener('beforeinstallprompt', this.handleBbeforeInstallAndroid);
      }
    }
  }

The logger in the handleBbeforeInstallAndroid method does display the received event fine.

But the logger in the receivedInstallPromptEventAndroid method shows an undefined installPromptEvent member variable.

The event listener is registered in the module:

const checkForBeforeInstallEvents: Function = (pwaService: PwaService) => () => pwaService.checkForBeforeInstallEvents();

@NgModule({
  providers: [
    {
      provide: APP_INITIALIZER,
      useFactory: checkForBeforeInstallEvents,
      deps: [PwaService],
      multi: true
    }
  ]
})
export class LibPwaModule { }

UPDATE: Folowing ConnorsFan's advice (I liked him a lot too at Flushing Meadows :-) I tried the following:

window.addEventListener('beforeinstallprompt', () => { this.handleBbeforeInstallAndroid });

but the method would simply not be called at all.

Then I tried an explicit bind statement as in:

window.addEventListener('beforeinstallprompt', this.handleBbeforeInstallAndroid.bind(this));

And this time, it worked fine and the this.installPromptEvent member variable was correctly retrieved.

As I got this from ConnorsFan's commment, I'd be happy to accept his solution.

Stephane
  • 11,836
  • 25
  • 112
  • 175
  • 1
    Can we see the `addEventListener` part? I am 90% sure that this is a duplicate of [this question](https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback). – ConnorsFan May 12 '20 at 13:24
  • 1
    Try `window.addEventListener('beforeinstallprompt', () => { this.handleBbeforeInstallAndroid(); });`. Or define the handler as an arrow function: `private handleBbeforeInstallAndroid = (event: Event): void => { ... }`. – ConnorsFan May 12 '20 at 13:42
  • 1
    Glad to know that (1) the suggestion worked and (2) you also like Jimmy Connors. :-) I will not post an answer since this is a duplicate of a frequently asked question. – ConnorsFan May 12 '20 at 15:22
  • 1
    In my original comment, I forgot the parentheses in the arrow function. That is why the function was not called. The modified comment should work. – ConnorsFan May 12 '20 at 15:25

0 Answers0