Send array params to a rails server from a JavaScript code – URL and URLSearchParams
The goal was to filter building instructions on buildin3d.com by brand. We had to parse and create the URL on the client so I played around with URL and URLSearchParams (again). I will try to summarize the implementation here in the hope that you could help understand how URL and URLSearchParams work and how to use them with a Ruby on Rails app.
Rails Server side request with array param
The server accepts a request in the form:
https://platform.buildin3d.com/instructions?in_categories[]=1&in_categories[]=2&in_categories[]=13
This means we could pass an array with the ids of the categories. The result will return only the 3D assembly instructions that are for Brands in these categories.
How to send the request on the client side
On the client side we have an <ul> element with some <li> elements representing the categories.
When we click on the brand we would like to add the brand to the URL and redirect the user to the new URL.
So if the current url is
https://platform.buildin3d.com/instructions?in_categories[]=1&in_categories[]=2
and we select a new brand I would like to send the user to
https://platform.buildin3d.com/instructions?in_categories[]=1&in_categories[]=2&in_categories[]=13
How to add array params to the URL with JavaScript
Here is the whole code of the Stimulus JS controller
import { Controller } from "stimulus";
/**
* This is a controller used for filtering by brands [categories] on the materials index page
*
* @author Kiril Mitov
*/
export default class extends Controller {
static targets = ["tree"];
connect() {
console.log("connect");
const scope = this;
this.setFromUrl();
this.treeTarget.addEventListener("click", e => {
e.preventDefault();
const li = e.target.closest("li");
const input = li.querySelector("input");
input.checked = !input.checked;
scope.goToNewLocation();
});
}
setFromUrl() {
const url = new URL(window.location);
const categoryIds = new URL(window.location).searchParams.getAll("in_categories[]")
Array.from(this.treeTarget.querySelectorAll("li[data-category-id]"))
.forEach(li => {
const input = li.querySelector("input");
const selected = categoryIds.indexOf(li.dataset["categoryId"]) != -1
input.checked = selected;
});
}
goToNewLocation() {
const url = new URL(window.location)
const searchParams = url.searchParams;
searchParams.delete("in_categories[]");
Array.from(this.treeTarget.querySelectorAll("li[data-category-id]"))
.filter(li => li.querySelector("input").checked)
.forEach(li => searchParams.append("in_categories[]",li.dataset["categoryId"]))
searchParams.sort();
window.location = url.toString();
}
}
There are a few important things in the code
Opening the page on a new location
window.location = url.toString()
This will open the new page for the user
Adding the selected brands to the url search query
We listen for an event of click from the user and we get a list of all the checked brands.
goToNewLocation() {
const url = new URL(window.location)
const searchParams = url.searchParams;
searchParams.delete("in_categories[]");
Array.from(this.treeTarget.querySelectorAll("li[data-category-id]"))
.filter(li => li.querySelector("input").checked)
.forEach(li => searchParams.append("in_categories[]",li.dataset["categoryId"]))
searchParams.sort();
window.location = url.toString();
}
First we delete the param “in_categories[]”. We use URLSearchParams.delete. This removes the param from the searchParam and if we then call .toString() we would receive the new search query without this param.
Then we call this.treeTarget.querySelectorAll to filter all the checkboxes and then only the check once and we append “in_categories[]” param for every selected checkbox. This is what the server requires.
searchParams.append("in_categories[]",li.dataset["categoryId"])
As a result with have the query
https://platform.buildin3d.com/instructions?in_categories[]=1&in_categories[]=2
Because we use only URLSearchParam.append and URLSearchParam.delete all the other params are still in the search query.
As a summary:
We have a Ruby on Rails server that accepts an array param and we form this array param in a Stimulus JS controller. We use URLSearchParams method to append and delete params, as this will preserve the other params that are already in the url.
Reply
You must be logged in to post a comment.