From 2a2f3818070d54cccfa64a8364ba315442e450b9 Mon Sep 17 00:00:00 2001 From: Chris Thielen Date: Wed, 31 Aug 2016 01:24:41 -0500 Subject: [PATCH] feat(ng2.rx): Added RxJS Observables for transitions and states: - Transitions started - Transitions successful - Parameter values - State registered - State deregistered --- src/ng2/providers.ts | 2 ++ src/ng2/rx.ts | 52 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 src/ng2/rx.ts diff --git a/src/ng2/providers.ts b/src/ng2/providers.ts index 47505228a..91226fe03 100644 --- a/src/ng2/providers.ts +++ b/src/ng2/providers.ts @@ -67,6 +67,7 @@ import {Resolvable} from "../resolve/resolvable"; import {ngModuleResolvablesBuilder} from "./statebuilders/lazyLoadNgModuleResolvable"; import {flattenR} from "../common/common"; import {UIROUTER_STATES_TOKEN} from "./uiRouterNgModule"; +import {UIRouterRx} from "./rx"; export const NG1_UIROUTER_TOKEN = new OpaqueToken("$uiRouter"); @@ -99,6 +100,7 @@ let uiRouterFactory = (injector: Injector) => { // ----------------- Create router ----------------- // Create a new ng2 UIRouter and configure it for ng2 let router = new UIRouter(); + new UIRouterRx(router); let registry = router.stateRegistry; // ----------------- Configure for ng2 ------------- diff --git a/src/ng2/rx.ts b/src/ng2/rx.ts new file mode 100644 index 000000000..8a4cc4475 --- /dev/null +++ b/src/ng2/rx.ts @@ -0,0 +1,52 @@ +import {Observable, ReplaySubject} from "rxjs/Rx"; +import {Transition} from "../transition/transition"; +import {UIRouter} from "../router"; +import {StateDeclaration} from "../state/interface"; + +export interface StatesChangedEvent { + currentStates: StateDeclaration[]; + registered: StateDeclaration[]; + deregistered: StateDeclaration[]; +} + +declare module '../globals' { + interface UIRouterGlobals { + states$?: Observable; + start$?: Observable; + success$?: Observable; + params$?: Observable<{ [paramName: string]: any }>; + } +} + +/** Augments UIRouterGlobals with observables for transition starts, successful transitions, and state parameters */ +export class UIRouterRx { + private deregisterFns: Function[] = []; + + constructor(router: UIRouter) { + let start$ = new ReplaySubject(1); + let success$ = > start$.mergeMap((t: Transition) => t.promise.then(() => t)); + let params$ = success$.map((transition: Transition) => transition.params()); + + let states$ = new ReplaySubject(1); + function onStatesChangedEvent(event: string, states: StateDeclaration[]) { + let changeEvent = { + currentStates: router.stateRegistry.get(), + registered: [], + deregistered: [] + }; + + if (event) changeEvent[event] = states; + states$.next(changeEvent); + } + + this.deregisterFns.push(router.transitionService.onStart({}, transition => start$.next(transition))); + this.deregisterFns.push(router.stateRegistry.onStatesChanged(onStatesChangedEvent)); + onStatesChangedEvent(null, null); + Object.assign(router.globals, {start$, success$, params$, states$}); + } + + dispose() { + this.deregisterFns.forEach(deregisterFn => deregisterFn()); + this.deregisterFns = []; + } +}