Last active
February 21, 2019 18:27
-
-
Save zdennis/2f73f60b4bfbab6b98ca3d2b9bfbc1fd to your computer and use it in GitHub Desktop.
Ionic + Angular: Re-use resolvers to load route data on cached pages
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
Component, | |
OnInit, | |
Input, | |
OnDestroy, | |
ViewChild, | |
} from '@angular/core'; | |
import { Order } from '../../orders/order'; | |
import { Subscription } from 'rxjs'; | |
import { ActivatedRoute, Data } from '@angular/router'; | |
import { IonRefresher } from '@ionic/angular'; | |
import { RouteDataResolutionService, RouteDataResolver } from 'src/app/framework-ext/route-data-resolution.service'; | |
@Component({ | |
selector: 'app-order-list-page', | |
templateUrl: './order-list-page.component.html', | |
styleUrls: ['./order-list-page.component.scss'] | |
}) | |
export class OrderListPageComponent implements OnInit, OnDestroy { | |
@Input() orders: Order[] = []; | |
@ViewChild(IonRefresher) | |
refresher: IonRefresher; | |
private refreshing = false; | |
private routeDataResolver: RouteDataResolver; | |
private subscriptions: Subscription[] = []; | |
constructor( | |
private activatedRoute: ActivatedRoute, | |
private routeDataResolutionService: RouteDataResolutionService, | |
) {} | |
ngOnInit() { | |
this.routeDataResolver = this.routeDataResolutionService.resolverFor(this.activatedRoute); | |
this.subscriptions.push( | |
this.routeDataResolver.data.subscribe(data => this.routeDataResolved(data)) | |
); | |
} | |
ngOnDestroy() { | |
this.subscriptions.forEach(s => s.unsubscribe()); | |
} | |
ionViewWillEnter() { | |
this.routeDataResolver.resolve(); | |
} | |
doRefresh() { | |
this.refreshing = true; | |
this.routeDataResolver.resolve(); | |
} | |
routeDataResolved(data: Data) { | |
this.orders = data.orders; | |
if (this.refreshing) { | |
this.refreshing = false; | |
this.refresher.complete(); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Injectable, Injector } from '@angular/core'; | |
import { ActivatedRoute, Router, Data } from '@angular/router'; | |
import { forkJoin, Subject, Observable, ReplaySubject } from 'rxjs'; | |
@Injectable({ | |
providedIn: 'root' | |
}) | |
export class RouteDataResolutionService { | |
constructor(private injector: Injector, private router: Router) {} | |
resolverFor(route: ActivatedRoute) { | |
return new RouteDataResolver(this.injector, this.router, route); | |
} | |
} | |
export class RouteDataResolver { | |
private subject = new ReplaySubject<Data>(1); | |
constructor( | |
private injector: Injector, | |
private router: Router, | |
private route: ActivatedRoute | |
) { | |
this.route.data.subscribe(data => this.subject.next(data)); | |
} | |
get data(): Observable<Data> { | |
return this.subject.asObservable(); | |
} | |
resolve() { | |
const routeResolve = this.route.routeConfig.resolve; | |
const props = Object.keys(routeResolve); | |
const resolvers = props.map(prop => this.injector.get(routeResolve[prop])); | |
const resolvedData: Data = {}; | |
const observables = resolvers.map(resolver => { | |
return resolver.resolve( | |
this.route.snapshot, | |
this.router.routerState.snapshot | |
); | |
}); | |
forkJoin(observables).subscribe(resolvedValues => { | |
props.forEach(prop => { | |
resolvedData[prop] = resolvedValues.shift(); | |
}); | |
this.subject.next(resolvedData); | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment