angular: Router does not reuse component when switching between different Routes that use the same component.

I’m submitting a … (check one with “x”)

[x] bug report => search github for a similar issue or PR before submitting
[ ] feature request
[ ] support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior

2 or more route declarations point to the same component. If a different route matches to the same component, the DOM and component are thrown away.

/hero/1 -> /hero/2 no issue, component stays around /hero/1 -> /hero/1/powers component is disposed of

Expected behavior

I should be able to change my route to anything and as long as it results in the same component being in the same routerOutlet, it should stay around. This is in reference to some comments in #9811

Minimal reproduction of the problem with instructions

In this example, my component should never be discarded and re-inited https://plnkr.co/edit/T7K4TfcTdHoqJ7HaFByS?p=preview

What is the motivation / use case for changing the behavior?

in the above example, powers could be a tab name I want to cue off of. It could be something I ngIf on, or any other number of things.

Please tell us about your environment:

MacOS, Sublimet Text, Npm

  • Angular version: 2.0.X

    2.1.1

  • Browser: [all | Chrome XX | Firefox XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView ]

    all

  • Language: [all | TypeScript X.X | ES6/7 | ES5] all

  • Node (for AoT issues): node --version =
    6.5.0

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 9
  • Comments: 42 (18 by maintainers)

Most upvoted comments

Hi @dewwwald, I think you might be interested how I achieved this goal by using custom router reuse strategy:

export class CustomRouteReuseStrategy extends RouteReuseStrategy {
    public shouldDetach(route: ActivatedRouteSnapshot): boolean { return false; }
    public store(route: ActivatedRouteSnapshot, detachedTree: DetachedRouteHandle): void {}
    public shouldAttach(route: ActivatedRouteSnapshot): boolean { return false; }
    public retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle { return null; }
    public shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
        return (future.routeConfig === curr.routeConfig) || future.data.reuse;
    }
}

And setting data: { reuse: true } for component route that should be reused. I described the details here: https://stackoverflow.com/questions/44875644/custom-routereusestrategy-for-angulars-child-module/44876414#44876414.

Sir, when you have a complex application, enterprises invest millions of dollars to build it.

One can build “some kind of application” with it. That kind of people are those who are just learning Angular2 or doing a proof of concepts.

But a framework that disregards such a basic tenet, needs to first realize the importance of what is missing.

What you are missing is that “Not destroying the components” is how applications are built today. You are adopting the approach of destroying - and expecting developers to waste their time to recreate that state, which is unnecessary and intrusive to the UI architecture. Why are you doing this? Is it just convenient for yourself. What would be the cost of this? Especially, when mainstream community finds out, then they may use the third party UI-Router. Only a novice developer will go to the work arounds, you mentioned. Seasoned UI developers can visualize the ditch that has been dug. So, the question is why is this not high priority? Angular2 is still in early stages. Later, the more people look at it, the more people will mock it. This is very fundamental to survival of the Router.

It is absolutely not about little inconvenience. One has to design every bit of the application differently with this serious limitation and one may run into issues that can never be implemented with the current approach.

@jamesmfriedman this is a very serious issue, which the router team is mistaking for a minor one. Can’t believe that they have gone so complex that they can’t provide a simple interface and invoke it with the active route. Any experienced single page app developer will be revolted to see the components being destroyed like this. The app is creating and destroying components all the time, as you navigate - for no obvious reason (because Framework demands that). Really funny!!! This is amateurish decision.

“Just a thought, the activate route could be an observable, like RouteParams, so you could still inject it, but you can watch it in case it changes.” @jamesmfriedman This is a great suggestion.

Thanks for mentioning UI Router. If push comes to shove, I am glad that there is UI-Router project.

But a framework that disregards a basic tenet,

This is absolutely not the case. As mentioned they plan to add this feature.

I still don’t get your point. Seek out some framework Xyz in version 27.9 and be happy with it instead of complaining that the first release of of a brand-new framework has a missing feature. Besides that I’m out of this discussion.

+1

On Tue, Oct 31, 2017 at 5:11 PM, Appie notifications@github.com wrote:

@zoechi https://github.com/zoechi Can this behavior of component recreation be prevented?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/angular/angular/issues/12446#issuecomment-340737020, or mute the thread https://github.com/notifications/unsubscribe-auth/ASVM_YERtqZB7bKsUjSDKNtiV01bpQiJks5sxwdZgaJpZM4KdieF .

there are easy workarounds for most use cases, therefore no need to make it a big deal

@zoechi Thank you for the great sources, I have been reading a lot of github issues and been through a ton of commits to the point I lost track of whether the feature I need is properly implemented or not. Turns out it is, and here is a demo of that for anybody that finds it hard to implement.

To use it just add a reuse: true boolean in your router configuration.

I know this isn’t how I should accomplish this, but it actually works as far as reusing the component without any hacks in Angular 5. In this case /user and /user/edit actually reuse the component even though UserComponent does not have a router outlet at all and is a child of itself.

const routes: Routes = [
  {
    path: '',
    component: UserLayoutComponent,
    children: [
      { 
        path: 'user', 
        component: UserComponent,
        children: [
          { path: 'edit', component: UserComponent }   // I'm not sure this needs to be UserComponent
        ]
      }
    ]
  }
];

Any insight here? Does anyone know of another way to accomplish this without a placeholder component?

@dewwwald I’m not on the Angular team, just an individual contributor and Angular user (just to avoid misunderstandings)

“I still don’t get your point. Seek out some framework Xyz in version 27.9 and be happy with it instead of complaining that the first release of of a brand-new framework has a missing feature. Besides that I’m out of this discussion.”

You have raised a very important point without realizing it. I must explain why I don’t pick up framework XYZ and be happy with it instead of complaining that the first release of of a brand-new framework has a missing feature.

I think Angular2 is revolutionary in many ways. It is this one limitation that screws it up really really bad. I hope you realize this.

Complaining is not bad if it can help avoid the blemish on an otherwise great framework? If I had read that this is high priority, I would not have written a single time, because I would know that this is being worked on. Once you say, that this is not high priority, I see the void between otherwise great framework and a framework with serious shortcoming.

You are inventing so many other features in the Router, that is admirable. But as a UI architect, I know that without this feature all the others are just glitter.

If you tell me you can’t build some kind of application because of this, then this sounds to me like you are not using Angular like it’s supposed to be used. I agree, that it is sometimes inconvenient but that doesn’t make it high priority, and it also was already confirmed that they want to add it eventually. So, I don’t see your point.

Just tried @DanielKucal reuse strategy above and its works awesome. Enables me to control what I want to reuse very simply.

currently seems like the way to go and very simple.

Thanks @DanielKucal for posting and anyone else involved.

I agree that this should work for a wider variety of scenarios. I have a complex component that can handle several type of urls and needs to remember the state of a tree widget that shows a hierarchy of data. Im using a service to keep that state and it’s being a pain in the a**. Need to keep track of what nodes are downloaded, what nodes are expanded, etc. Lot of coding that could be saved if angular were more flexible about this.

@zoechi Can this behavior of component recreation be prevented?

@martinsik it does, but only when it’s the same route (only route parameter change) If you have 2 different routes with the same component, the component is destroyed and recreated by default.

@zoechi, appreciate the work you and your team mates put in to Angular2.

I would like to see what I can do from my side to help this feature be implemented. Or I might be approaching this wrong.

I have the following routes

‘foo/:hello/:world/:page’, component: FooComponent ‘foo/:hello/:world/’, component: FooComponent

In the above case :page is basically a pagination of FooComponent. :world is a type and though :world changes the component FooComponent Remains the same (as you can gather).

I can use query params to paginate as that solved the problem. However, I would like the switching between routes that have matching components to not re-render all of the component. I think it will have a SEO benifit to have unique path-segments in place of query params (might be better I am still testing the theory).

So any suggestions would be great. I will read the above resource. However I just wanted to add my case as an illustration of when this happens and also be number in the devs with the problem count 😃.

Regards, Dewald.

Well in your example you’re still navigating between routes (i.e. you’ve triggered a different node in your route configuration tree). It just happens that the route renders the same component in the same outlet. The parameter change stuff is irrelevant because it’s a different node.

I think what the docs aren’t saying (but are implying) is that you only get component reuse when the navigation triggers the exact same configuration node…?

That said, I’m not a team member – I have no idea what the ultimate intent is here.