Angular 9 URL Parameters

0
2783

It’s come to my attention that some people are confused about routing in Angular. Specifically, there’s some confusion around retrieving parameters from the URL and query string. It’s a fairly simple task but it might help to work through an example together. Luckily for you, I created a StackBlitz that helps to explain the differences between using the snapshot and subscription. Let’s take a look at it.


Routes

For our purposes, let’s focus on route parameters. We are going to create the route "animals/:animal". With this route, we can navigate to animals/dog or animals/cat to retrieve either dog or cat from the :animal parameter.

 { path: "animals/:animal", component: AnimalsComponent }

The colon is the giveaway. That’s what makes the second part of the URL a parameter.

Accessing the URL

Angular provides us with the ActivatedRoute object. We can access the URL through this object, but first, you have to inject it into your component. Inject it like any other service:

import { ActivatedRoute } from "@angular/router";
constructor(private route: ActivatedRoute) { }

Accessing URL Parameters

There are two generally accepted ways to access URL parameters. One is through route.snapshot.paramMap and the other is through route.paramMap.subscribe. The main difference between the two is that the subscription will continue to update as the parameter changes for that specific route. This is easier to show than explain, so make sure to play with the StackBlitz example.

Snapshot

Using the snapshot is, as the name suggests, a one-time event. A typical use case is to get the parameter when the component loads. Read the code explicitly; when I load the component I will get the URL parameter.

ngOnInit() {
  this.animal = this.route.snapshot.paramMap.get("animal")
}

This strategy will not work if the parameter changes within the same component. More explicitly, changing from animals/dog to animals/cat will not destroy and initialize the AnimalComponent, so the ngOnInit method doesn’t get called a second time.

Subscription

Using the subscription is the same as any other subscription. If there is a change then the observable’s value will get pushed to the callback function. If this is unclear then do some homework and read up on RxJS. I’ve also written about it. This strategy is only useful if the URL parameter(s) are changing within the current route.

ngOnInit() {
  this.route.paramMap.subscribe(params => {
    this.animal = params.get("animal")
  })
}

This strategy might be overkill but it’s definitely the safest strategy if you’re still confused.

Also, there’s no need to unsubscribe from the paramMap. The ActivatedRoutedies with the routed component and so the subscription dies with it.


Accessing Query Parameters

Accessing query string parameters is similar to accessing URL parameters. It’s just a different property on the ActivatedRoute object; queryParamMap. So all the same principles apply, but make sure to use the right property.

ngOnInit() {
  this.name = this.route.snapshot.queryParamMap.get("paramName")
  this.route.queryParamMap.subscribe(queryParams => {
    this.name = queryParams.get("paramName")
  })
}

Advanced — Using switchMap

During my research, I found an Angular example that piped the parameters through a switchMap. What is a switchMap? Long answer: I don’t know. Short answer: It basically cancels a request as a new one comes in.

For example, if I subscribe to the paramMap and I start spamming changes to the route parameters, switchMap will cancel any pending requests and pick up the new request. This is overkill in most cases but it could be useful.

import { switchMap } from "rxjs/operators" // RxJS v6
ngOnInit() {
  this.route.paramMap.pipe(
    switchMap(params => {
      this.animal = params.get("animal")
    })
  )
}

WAIT! The code above doesn’t reflect the Angular example. I’m overlooking their HTTP request within the switchMap. Let’s dive a little deeper with the example below.

ngOnInit() {
  this.data = this.route.paramMap.pipe(
    switchMap(params => {
      const id = +params.get("id")
      return this.service.getData(id) // http request
    })
  )
}

In the example above, I’m making an HTTP request within the paramMapsubscription. I hope we all know that HTTP requests are relatively expensive. If I’m spamming parameter changes, I will want to cancel any previous requests. In this case, using switchMap will do just that and therefore improve performance.


Conclusion

All-in-all, getting parameters from the URL is pretty simple. Use the snapshot for a one-time grab or a subscription if the parameters can change within the same component/route. If you make an HTTP request within the subscription then use switchMap to cancel any unnecessary pending request.