I needed to cancel the route on promise rejection and stay on the current page without redirecting to default/error page, I have tried different ways of rejecting the promise but ended up resolving the route or redirected to the default route.
@Injectable()
export class ModelResolver implements Resolve<MyModel> {
constructor(private router: Router) {
}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<any> {
let params: any = route.params;
let model: MyModel= new MyModel();
return model.init().then((obj: MyModel) => {
return obj;
}).catch((err: any) => {
Promise.reject({message: err , ngNavigationCancelingError: true});
});
}
}
reject({message: err , ngNavigationCancelingError: true});
// redirects to my default route
return Observable.throw({message: err , ngNavigationCancelingError: true});
// redirects to the current route without cancelling
resolve(null); or return Observable.empty()
// redirects to the current route without cancelling
In order to cancel route from resolver, you can use observable instead of promise and call: observer.complete() without calling: observer.next()
For example:
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot){
return new Observable((observer) => {
let somePromiseOrObservableToGetDate=?????;
somePromiseOrObservableToGetDate.then(data => {
if (data) {
observer.next(1);
}
observer.complete();
})
.catch((err: any) => {
observer.complete();
});
});
}
and in your example:
let model: MyModel = new MyModel();
return new Observable((observer) => {
model.init().then((obj: any) => {
observer.next(obj);
observer.complete();
})
.catch((err: any) => {
observer.complete();
});
});
Using Angular 6 the only way I could prevent the navigation from happening was throwing an unhandled error from the resolver stream. The simplest way to test this out:
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
// throwError imported from 'rxjs'.
return throwError('some error object');
}
The navigation would also not happen if you'd return a stream that never completes (ie. NEVER
from 'rxjs'
) but then the router would keep on waiting for the stream to either complete or error (which never happens) meaning all routing operations will stop working.
UPDATE 2021:
This is not found in the resolver docs but Angular 10 upgrade guide mentions that:
Any resolver which returns EMPTY will cancel navigation. If you want to allow navigation to continue, you will need to update the resolvers to emit some value, (i.e. defaultIfEmpty(...), of(...), etc).
Tried it out with EMPTY
and this indeed works now. There's no longer a need to throw an error to cancel the navigation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With