I have two pages: login and account. There are two scenarios:
- first route is
/login - first route is
/account
First route is when, for example, I open chrome and type localhost:8100/login /login would be the first route.
First scenario, when first route is /login:
- user is currently at
/login; - user loggs in to account1 and now user is at
/account; /accountshows account1 data;- user loggs out and goes back to
/login; - user loggs in to account2 goes to
/account; /accountshow account2 data as it should.
Second scenario, when first route is /account:
- user is currently at
/accountand is logged in to account1; - user loggs out and goes to
/login; - user loggs in to account2 and goes back to
/account; /accountshows account1 data instead of account2 and the ngOnInit was not called.
I'm guessing, the problem is when the first route is /account it is saved, and reused by Angular.
I have implemented a custom route reuse strategy, it works perfectly. I set /account route to not be reused by the strategy. And it is not, it is not saved in storedRoutes, variable where saved routes are. But it is reused anyway. Same thing with /login route: when /login route is the first route it is saved, not by my custom RRS, and angular reuses it.
this is the custom route reuse strategy:
class CustomRouteReuseStrategy implements RouteReuseStrategy {
/**
* Object which will store RouteStorageObjects indexed by keys
* The keys will all be a path (as in route.routeConfig.path)
* This allows us to see if we've got a route stored for the requested path
*/
storedRoutes: { [key: string]: RouteStorageObject } = {};
/**
* Decides when the route should be stored
* If the route should be stored, I believe the boolean is indicating to a controller whether or not to fire this.store
* _When_ it is called though does not particularly matter, just know that this determines whether or not we store the route
* An idea of what to do here: check the route.routeConfig.path to see if it is a path you would like to store
* @param route This is, at least as I understand it, the route that the user is currently on, and we would like to know if we want to store it
* @returns boolean indicating that we want to (true) or do not want to (false) store that route
*/
shouldDetach(route: ActivatedRouteSnapshot): boolean {
const detach: boolean = route.data.routeReuse === true;
return detach;
}
/**
* Constructs object of type `RouteStorageObject` to store, and then stores it for later attachment
* @param route This is stored for later comparison to requested routes, see `this.shouldAttach`
* @param handle Later to be retrieved by this.retrieve, and offered up to whatever controller is using this class
*/
store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
const storedRoute: RouteStorageObject = {
snapshot: route,
handle: handle
};
// routes are stored by path - the key is the path name, and the handle is stored under it so that you can only ever have one object stored for a single path
this.storedRoutes[route.routeConfig.path] = storedRoute;
}
/**
* Determines whether or not there is a stored route and, if there is, whether or not it should be rendered in place of requested route
* @param route The route the user requested
* @returns boolean indicating whether or not to render the stored route
*/
shouldAttach(route: ActivatedRouteSnapshot): boolean {
// this will be true if the route has been stored before
const canAttach: boolean = !!route.routeConfig && !!this.storedRoutes[route.routeConfig.path];
// this decides whether the route already stored should be rendered in place of the requested route, and is the return value
// at this point we already know that the paths match because the storedResults key is the route.routeConfig.path
// so, if the route.params and route.queryParams also match, then we should reuse the component
if (canAttach) {
const willAttach: boolean = true;
const paramsMatch: boolean = this.compareObjects(route.params, this.storedRoutes[route.routeConfig.path].snapshot.params);
const queryParamsMatch: boolean = this.compareObjects(route.queryParams, this.storedRoutes[route.routeConfig.path].snapshot.queryParams);
return paramsMatch && queryParamsMatch;
} else {
return false;
}
}
/**
* Finds the locally stored instance of the requested route, if it exists, and returns it
* @param route New route the user has requested
* @returns DetachedRouteHandle object which can be used to render the component
*/
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
// return null if the path does not have a routerConfig OR if there is no stored route for that routerConfig
if (!route.routeConfig || !this.storedRoutes[route.routeConfig.path]) return null;
/** returns handle when the route.routeConfig.path is already stored */
return this.storedRoutes[route.routeConfig.path].handle;
}
/**
* Determines whether or not the current route should be reused
* @param future The route the user is going to, as triggered by the router
* @param curr The route the user is currently on
* @returns boolean basically indicating true if the user intends to leave the current route
*/
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
return future.routeConfig === curr.routeConfig;
}
}