HiveBrain v1.2.0
Get Started
← Back to all entries
snippetjavascriptangularCritical

How to implement RouteReuseStrategy shouldDetach for specific routes in Angular 2

Submitted by: @import:stackoverflow-api··
0
Viewed 0 times
angularshoulddetachhowforroutereusestrategyroutesspecificimplement

Problem

I have an Angular 2 module in which I have implemented routing and would like the states stored when navigating.

The user should be able to:

  • search for documents using a 'search formula'



  • navigate to one of the results



  • navigate back to 'searchresult' - without communicating with the server



This is possible including RouteReuseStrategy.

The question is:

How do I implement that the document should not be stored?

So the route path "documents"'s state should be stored and the route path "documents/:id"' state should NOT be stored?

Solution

Hey Anders, great question!

I've got almost the same use case as you, and wanted to do the same thing! User search > get results > User navigates to result > User navigates back > BOOM blazing fast return to results, but you don't want to store the specific result that the user navigated to.

tl;dr

You need to have a class that implements RouteReuseStrategy and provide your strategy in the ngModule. If you want to modify when the route is stored, modify the shouldDetach function. When it returns true, Angular stores the route. If you want to modify when the route is attached, modify the shouldAttach function. When shouldAttach returns true, Angular will use the stored route in place of the requested route. Here's a Plunker for you to play around with.

About RouteReuseStrategy

By having asked this question, you already understand that RouteReuseStrategy allows you to tell Angular not to destroy a component, but in fact to save it for re-rendering at a later date. That's cool because it allows:

  • Decreased server calls



  • Increased speed



  • AND the component renders, by default, in the same state it was left



That last one is important if you would like to, say, leave a page temporarily even though the user has entered a lot of text into it. Enterprise applications will love this feature because of the excessive amount of forms!

This is what I came up with to solve the problem. As you said, you need to make use of the RouteReuseStrategy offered up by @angular/router in versions 3.4.1 and higher.

TODO

First Make sure your project has @angular/router version 3.4.1 or higher.

Next, create a file which will house your class that implements RouteReuseStrategy. I called mine reuse-strategy.ts and placed it in the /app folder for safekeeping. For now, this class should look like:

import { RouteReuseStrategy } from '@angular/router';

export class CustomReuseStrategy implements RouteReuseStrategy {
}


(don't worry about your TypeScript errors, we're about to solve everything)

Finish the groundwork by providing the class to your app.module. Note that you have not yet written CustomReuseStrategy, but should go ahead and import it from reuse-strategy.ts all the same. Also import { RouteReuseStrategy } from '@angular/router';

@NgModule({
[...],
providers: [
{provide: RouteReuseStrategy, useClass: CustomReuseStrategy}
]
)}
export class AppModule {
}


The final piece is writing the class which will control whether or not routes get detached, stored, retrieved, and reattached. Before we get to the old copy/paste, I'll do a short explanation of mechanics here, as I understand them. Reference the code below for the methods I'm describing, and of course, there's plenty of documentation in the code.

  • When you navigate, shouldReuseRoute fires. This one is a little odd to me, but if it returns true, then it actually reuses the route you're currently on and none of the other methods are fired. I just return false if the user is navigating away.



  • If shouldReuseRoute returns false, shouldDetach fires. shouldDetach determines whether or not you want to store the route, and returns a boolean indicating as much. This is where you should decide to store/not to store paths, which I would do by checking an array of paths you want stored against route.routeConfig.path, and returning false if the path does not exist in the array.



  • If shouldDetach returns true, store is fired, which is an opportunity for you to store whatever information you would like about the route. Whatever you do, you'll need to store the DetachedRouteHandle because that's what Angular uses to identify your stored component later on. Below, I store both the DetachedRouteHandle and the ActivatedRouteSnapshot into a variable local to my class.



So, we've seen the logic for storage, but what about navigating to a component? How does Angular decide to intercept your navigation and put the stored one in its place?

  • Again, after shouldReuseRoute has returned false, shouldAttach runs, which is your chance to figure out whether you want to regenerate or use the component in memory. If you want to reuse a stored component, return true and you're well on your way!



  • Now Angular will ask you, "which component do you want us to use?", which you will indicate by returning that component's DetachedRouteHandle from retrieve.



That's pretty much all the logic you need! In the code for reuse-strategy.ts, below, I've also left you a nifty function that will compare two objects. I use it to compare the future route's route.params and route.queryParams with the stored one's. If those all match up, I want to use the stored component instead of generating a new one. But how you do it is up to you!

reuse-strategy.ts

`/**
* reuse-strategy.ts
* by corbfon 1/6/17
*/

import { ActivatedRouteSnapshot, RouteReuseStrategy, DetachedRouteHandle } from '@angular/router';

/*

Context

Stack Overflow Q#41280471, score: 313

Revisions (0)

No revisions yet.