Skip to content

Instantly share code, notes, and snippets.

@zdennis
Last active February 21, 2019 18:27
Show Gist options
  • Save zdennis/2f73f60b4bfbab6b98ca3d2b9bfbc1fd to your computer and use it in GitHub Desktop.
Save zdennis/2f73f60b4bfbab6b98ca3d2b9bfbc1fd to your computer and use it in GitHub Desktop.
Ionic + Angular: Re-use resolvers to load route data on cached pages
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();
}
}
}
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