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?
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 thengModule
. If you want to modify when the route is stored, modify theshouldDetach
function. When it returnstrue
, Angular stores the route. If you want to modify when the route is attached, modify theshouldAttach
function. WhenshouldAttach
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:
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 minereuse-strategy.ts
and placed it in the/app
folder for safekeeping. For now, this class should look like:(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 writtenCustomReuseStrategy
, but should go ahead andimport
it fromreuse-strategy.ts
all the same. Alsoimport { RouteReuseStrategy } from '@angular/router';
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.
shouldReuseRoute
fires. This one is a little odd to me, but if it returnstrue
, 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.shouldReuseRoute
returnsfalse
,shouldDetach
fires.shouldDetach
determines whether or not you want to store the route, and returns aboolean
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 againstroute.routeConfig.path
, and returning false if thepath
does not exist in the array.shouldDetach
returnstrue
,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 theDetachedRouteHandle
because that's what Angular uses to identify your stored component later on. Below, I store both theDetachedRouteHandle
and theActivatedRouteSnapshot
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?
shouldReuseRoute
has returnedfalse
,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, returntrue
and you're well on your way!DetachedRouteHandle
fromretrieve
.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'sroute.params
androute.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
Behavior
This implementation stores every unique route that the user visits on the router exactly once. This will continue to add to the components stored in memory throughout the user's session on the site. If you'd like to limit the routes that you store, the place to do it is the
shouldDetach
method. It controls which routes you save.Example
Say your user searches for something from the homepage, which navigates them to the path
search/:term
, which might appear likewww.yourwebsite.com/search/thingsearchedfor
. The search page contains a bunch of search results. You'd like to store this route, in case they want to come back to it! Now they click a search result and get navigated toview/:resultId
, which you do not want to store, seeing as they'll probably be there only once. With the above implementation in place, I would simply change theshouldDetach
method! Here's what it might look like:First off let's make an array of paths we want to store.
now, in
shouldDetach
we can check theroute.routeConfig.path
against our array.Because Angular will only store one instance of a route, this storage will be lightweight, and we'll only be storing the component located at
search/:term
and not all the others!Additional Links
Although there's not much documentation out there yet, here are a couple links to what does exist:
Angular Docs: https://angular.io/docs/ts/latest/api/router/index/RouteReuseStrategy-class.html
Intro Article: https://www.softwarearchitekt.at/post/2016/12/02/sticky-routes-in-angular-2-3-with-routereusestrategy.aspx
nativescript-angular's default Implementation of RouteReuseStrategy: https://github.com/NativeScript/nativescript-angular/blob/cb4fd3a/nativescript-angular/router/ns-route-reuse-strategy.ts