DEV Community

Cover image for TIL: URLSearchParams
Tim Deschryver
Tim Deschryver

Posted on • Originally published at timdeschryver.dev

TIL: URLSearchParams

Follow me on Twitter at @tim_deschryver | Subscribe to the Newsletter | Originally published on timdeschryver.dev.


It has been a while that I had the need to read and write query parameters from an URL myself because Angular abstracts all of this away in the @angular/router package. But because my personal blog is written with Svelte and I wanted to have a feature to search for blog posts, I had to write it myself this time.

From my experience with query strings, during the jQuery era, this wasn't straight forward.
But today I learned about the URLSearchParams API and now it is super easy!

Let's take a look at an example.

We have the URL https://timdeschryver.dev/blog?q=Angular+NgRx and we want want to retrieve the query params to filter blog posts based on the q parameter.

To create the URLSearchParams we need to access the query string, this is available on the search property of the location. With it, we can create a new instance of URLSearchParams.

console.log(location.search)
// |> '?q=Angular+NgRx'
const params = new URLSearchParams(location.search)
Enter fullscreen mode Exit fullscreen mode

While writing this blog post, I also discovered that the search params are available on URL instances and on anchor tags (<a>).

const url = new URL(location.search)
const params = url.searchParams

const node = document.querySelector('#search')
const url = new URL(node.href)
const params = new URLSearchParams(node.search)
Enter fullscreen mode Exit fullscreen mode

So now that we have params, what can we do with it?

We can read a query parameter with the get method.

params.get('q')
// |> 'Angular NgRx'
Enter fullscreen mode Exit fullscreen mode

We can set a query parameter with the set method.

params.set('q', 'Performance')
Enter fullscreen mode Exit fullscreen mode

We can delete a query parameter with the delete method.

params.delete('q')
Enter fullscreen mode Exit fullscreen mode

So easy!
We don't have to manually parse the query parameters ourselves and we're sure that it's bug-free.
There are even not all the available methods, these are just the ones I used and I think are the ones that are used the most.

Navigating

Setting and deleting the search params doesn't change the current location.
To modify the current location we can make use of the history.replaceState method and pass it the new URL.

The stringified version of params will concatenate all keys and values to one query string.

console.log(params.toString())
// |> q=Testing+Library
Enter fullscreen mode Exit fullscreen mode

Together with the current pathname, we can create a new URL.

window.history.replaceState(
  window.history.state,
  '',
  `${location.pathname}?${params}`,
)
Enter fullscreen mode Exit fullscreen mode

Example code

I ended up with the following code to set a new URL and to filter the blog posts.
Using the svelte reactive statements it's simple to react to value changes and makes the whole flow easy to read.

// instantiate with the query parameter
// query is bound to an input element (<input bind:value={query} type="search"  />)
let query = $page.query['q'] || ''

// change the URL when the query is changed
$: if (typeof window !== 'undefined') {
  let params = new URLSearchParams(window.location.search)

  if (query) {
    params.set('q', query)
    window.history.replaceState(
      window.history.state,
      '',
      `${location.pathname}?${params}`,
    )
  } else {
    params.delete('q')
    window.history.replaceState(window.history.state, '', location.pathname)
  }
}

// filter posts based on the query
$: if (query) {
  filteredPosts = posts.filter(p => {
    return queryParts.every(
      q =>
        p.metadata.tags.some(t => match(t, q)) ||
        like(p.metadata.title, q) ||
        like(p.metadata.description, q),
    )
  })
} else {
  filteredPosts = posts
}
Enter fullscreen mode Exit fullscreen mode

Further reading


Follow me on Twitter at @tim_deschryver | Subscribe to the Newsletter | Originally published on timdeschryver.dev.

Top comments (0)