94

What is the difference between ActivatedRouteSnapshot and ActivatedRoute in Angular 4? It's my understanding that ActivatedRouteSnapshot is a child of ActivatedRoute, meaning that ActivatedRoute contains ActivatedRouteSnapshot.

Incidentally, I tried running a Google search for an answer to this question, but I didn't find any of the search results to be understandable.

Thank you!

user2245766
  • 301
  • 1
  • 10
RajnishCoder
  • 3,455
  • 6
  • 20
  • 35

3 Answers3

95

Since ActivatedRoute can be reused, ActivatedRouteSnapshot is an immutable object representing a particular version of ActivatedRoute. It exposes all the same properties as ActivatedRoute as plain values, while ActivatedRoute exposes them as observables.

Here is the comment in the implementation:

export class ActivatedRoute {
  /** The current snapshot of this route */
  snapshot: ActivatedRouteSnapshot;

If a router reuses a component and doesn't create a new activated route, you will have two versions of ActivatedRouteSnapshot for the same ActivatedRoute. Suppose you have the following routing configuration:

path: /segment1/:id,
component: AComponent

Now you navigate to:

/segment1/1

You will have the param in the activatedRoute.snapshot.params.id as 1.

Now you navigate to:

/segment1/2

You will have the param in the activatedRoute.snapshot.params.id as 2.

You can see it by implementing the following:

export class AComponent {
  constructor(r: ActivatedRoute) {    
    r.url.subscribe((u) => {
      console.log(r.snapshot.params.id);
    });
Max Koretskyi
  • 101,079
  • 60
  • 333
  • 488
  • 1
    Are you sure about the middle section? If you navigate to the same component with different param,then snapshot should not be updated..... – Royi Namir Mar 26 '18 at 19:46
  • @RoyiNamir, do you have a demo to show it? If it's the case, I'll update my answer. Thanks – Max Koretskyi Mar 27 '18 at 09:00
  • 2
    [**Here is a demo**](https://stackblitz.com/edit/angular-4qkzkx?file=ProductDetails.component.ts) . Using snapshot - doesn't show the right ID when clicking. So your statement [here](https://i.imgur.com/j4hYbif.jpg) is incorrect – Royi Namir Apr 03 '18 at 17:26
  • @RoyiNamir, the link is broken. Can you please fix it? – Max Koretskyi Apr 04 '18 at 05:22
  • https://stackblitz.com/edit/angular-router-snapshot-and-params-yakov?file=ProductDetails.component.ts – Royi Namir Apr 04 '18 at 09:27
  • @RoyiNamir, it updates the snapshot, here is the demo: https://stackblitz.com/edit/angular-router-snapshot-and-params-yakov-hzkxd9?file=ProductDetails.component.ts. The `id` that comes as a parameter to a callback is the same as in the snapshot – Max Koretskyi Apr 04 '18 at 13:14
  • You go through subscribe. sure it would. but snapshot - its main rule - is to get value without needing to be subscribed. if the component is destroyed and then you go to a new component - then you'd be able to see snapshot changing. – Royi Namir Apr 04 '18 at 13:15
  • 1
    @RoyiNamir, it's not about subscribe, I've updated the example. No subscribe there – Max Koretskyi Apr 04 '18 at 14:30
  • 2
    I guess I meant that ctor won't be called again ( nor ngOninit) - so the code which reads the snapshot will not be called. But - as you showed - it doesn't mean that parameter won't be updated. – Royi Namir Apr 05 '18 at 10:40
  • ActivatedRoute.routeConfig is not an Observable, so is it the same of ActivatedRouteSnapshot.routeConfig? – Luke May 23 '18 at 12:40
  • @Luke, you can easily check it yourself – Max Koretskyi May 24 '18 at 05:31
  • I checked, they are the same. – Luke May 24 '18 at 07:34
  • @Luke, so what is your question? – Max Koretskyi May 24 '18 at 09:27
  • What's the point of having ActivatedRoute.routeConfig and ActivatedRouteSnapshot.routeConfig if they are the same, when to use one or the other, etc.? – Luke May 24 '18 at 09:32
  • @Luke, becauase ActivatedRoute and ActivatedRouteSnapshot have different purposes and you may want to use only one of them. It would be inconvenient if you had to use the other one just to get `routeConfig` – Max Koretskyi May 24 '18 at 09:35
  • I think this answer is a little misleading/confusing... so I made my own. Your "proof" example at the end I think just makes it more confusing. – Don Cheadle Nov 10 '18 at 19:24
60

There are 2 ways to get the parameter from the route.

1. Snapshot (route.snapshot.paramMap.get). Read it during init.

Use the Snapshot if you only need the initial value of the parameter once during the component's initialization, and don't expect the URL to change while the user is still on that same component.

  • I.e. if on a product/2 route, and the only way they'd get to product/3 is by going back to the product search screen and then clicking a product detail (leaving the detail component, then re-opening it with a new route param)

2. Observable (route.paramMap.subscribe). Subscribe to it during init.

Use the Observable if it's possible for the route to change while the user is still on the same component, and hence the Component's initialization would not be called again, but the observable would call your subscribed logic when the URL changed.

  • I.e. if on a product/2 route, and you have a "next" button to go to the next id record product/3, hence the user did not leave/re-open the component but the URL did receive a new param.

Generally speaking, subscribing is the safest route if you're unsure.

Community
  • 1
  • 1
Don Cheadle
  • 5,224
  • 5
  • 39
  • 54
  • 1
    Would subscribing to an observable count as "real work" that should be done in `ngOnInit` instead of the constructor? – Charles Wood Jan 07 '19 at 15:55
19

One of the key differences not highlighted by the other answers here is the fact that ActivatedRoute can be injected into a component, while ActivatedRouteSnapshot cannot.

As mentioned in this answer, you access ActivatedRouteSnapshot in a component by injecting ActivatedRoute, and then accessing its snapshot property, like so:

constructor(route: ActivatedRoute) { 
  let activatedRouteSnapshot = route.snapshot;
}

On the other hand, trying to inject ActivatedRouteSnapshot directly into the component will result in an error like this:

ERROR Error: Uncaught (in promise): Error: StaticInjectorError(AppModule)[YourComponent -> ActivatedRouteSnapshot]: StaticInjectorError(Platform: core)[YourComponent -> ActivatedRouteSnapshot]: NullInjectorError: No provider for ActivatedRouteSnapshot!

See also the documentation for ActivatedRoute and ActivatedRouteSnapshot

peregrination
  • 2,460
  • 1
  • 25
  • 21