Ionic Page Events as Observable

A little decorator to move Ionic Page events from callback pattern to observable pattern.

Source code

import { Observable, Subject } from "rxjs";
import { filter, map, tap } from "rxjs/operators";

export function IonPageEvent(event: "ionViewWillEnter" | "ionViewDidEnter" | "ionViewDidLeave" | "ionViewWillUnload" | "ionViewWillLeave" | "ngOnDestroy") {
  
  return (target: object, propertyKey: string) => {
    
    let subjectName = event + "_as_subject";

    let obs = () => {
      return target[propertyKey] as Observable<string>;
    };
    let sub = () => {
      return target[subjectName] as Subject<string>;
    };
    Object.defineProperty(target, propertyKey, {
      get: () => sub().asObservable()
    });

    if (!target[subjectName]) {
      Object.defineProperty(target, subjectName, {
        value: new Subject<string>()
      });
      let orig = Object.getOwnPropertyDescriptor(target, event);

      obs()
        .pipe(
          filter(() => orig && typeof orig.value == "function"),
          tap(() => {
            console.log("CALLING ORIGINAL", target);
          }),
          map(() => orig.value as Function),
          tap(f => f.apply(target, []))
        )
        .subscribe();

      //override native method
      target[event] = () => {
        console.info(IonPageEvent.name, event, "from", target.constructor.name);
        sub().next(event);
      };

      console.assert(target[subjectName] instanceof Subject);
      console.assert(target[propertyKey] instanceof Observable);
      console.assert(target[event] instanceof Function);
      console.info(IonPageEvent.name, event, "config done on page", target.constructor.name);
    }
  };
}

Usage example

import IonPageEvent from "./pageEventsAsObservable.ts";

export class HomePage {
 
  
  ngOnInit(){
  	this.OnDidEnter.subscribe(()=>{
      console.log("enter");
    });
    
    this.OnWillLeave.subscribe(()=>{
      console.log("will leave");
    });
  }
  
  @IonPageEvent("ionViewDidEnter")
  OnDidEnter:Subject<any>;
  
  @IonPageEvent("ionViewWillLeave")
  OnWillLeave:Subject<any>;
  
}

Todo

  • NPM package
  • Move from Subject Type to Observable Type
  • Do not use console API