Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: URL.setSearchParams() #828

Open
jeremy-code opened this issue May 23, 2024 · 3 comments
Open

Proposal: URL.setSearchParams() #828

jeremy-code opened this issue May 23, 2024 · 3 comments
Labels
addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest topic: api

Comments

@jeremy-code
Copy link

jeremy-code commented May 23, 2024

What problem are you trying to solve?

Effectively, for a URL object, setting the searchParams (and by extension search) to some URLSearchParams object.

Currently, the searchParams property is read-only (see: URL: searchParams property). Hence, to update the searchParams, one would have to update the search string property manually instead.

This is not ideal as developers may want to work in terms of objects rather than strings (new URLSearchParams({ foo: "bar", baz: "qux" }) is much more readable compared to "?foo=bar&baz=qux").

Being able to set the searchParams property without having to go through a string intermediate can be a pretty common case, such as appending multiple entries at once, or initializing with some default values.

What solutions exist today?

Today, to update the searchParams, one would either have to run the delete() method for all current entries and set() for all new entries (which is impractical) or update the search string property manually such as:

function setUrlSearchParams(url, searchParams) {
  if (searchParams.size === 0 || searchParams === null) {
    url.search = "";
  }
  url.search = "?" + searchParams.toString();
}

However, since URLSearchParams.toString() and URL.search are not the same value, this is slightly more complicated

The toString() does not include the question mark ?, while URL.search does. This doesn't mean just by appending "?" that the proper value, since for both, an empty string is equivalent to a null query.

How would you solve it?

I am not certain on the implementation details of the function, since just implementing the setUrlSearchParams() shown earlier method seems redundant (as you would have to parse the string into a URLSearchParams object to get the new .searchParams property), but in general, having a function URL.setSearchParams can make some tasks easier.

For instance, for the cases I mentioned:

Intializing a URL with default values

// previously, with string immediate
const url = new URL(`https://example.com?${new URLSearchParams({ foo: "bar", baz: "qux" })}`);
const url = new URL("https://example.com?foo=bar&baz=qux");

// with a setSearchParams() method
const url = new URL("https://example.com")
url.setSearchParams(new URLSearchParams({ foo: "bar", baz: "qux" }))

Appending multiple entries

// url already has search parameters
const url = new URL(`https://example.com?${new URLSearchParams({ foo: "bar", baz: "qux" })}`);
url.setSearchParams(new URLSearchParams([["foo", "bar"], ["baz", "qux"], ...url.searchParams]));

Anything else?

EDIT: I apologize, I just noticed this is very similar to #413.

@jeremy-code jeremy-code added addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest labels May 23, 2024
@annevk
Copy link
Member

annevk commented May 23, 2024

We could maybe add a searchParams a setter. I don't think we need a separate method. The one question I see is what should happen if URLSearchParams already has an associated URL. We'd have to decide between throwing or changing the URL association (and updating both the old and new URL). I don't think we want to end up in a situation where a single URLSearchParams can be associated with multiple URLs.

@jasnell
Copy link
Collaborator

jasnell commented May 23, 2024

I think a searchParams setter makes the most sense but I also don't see this as a critical issue to address and would likely prefer not to change this.

The one question I see is what should happen if URLSearchParams already has an associated URL. We'd have to decide between throwing or changing the URL association (and updating both the old and new URL). I don't think we want to end up in a situation where a single URLSearchParams can be associated with multiple URLs.

I think there are a few options here.

  1. The setter could be defined to essentially clone/copy the given URLSearchParams as opposed to storing it by reference. It could be a bit odd in some cases in that the following would hold true url.searchParams = newSearchParams; url.searchParams !== newSearchParams but it would address the URL link issue.

  2. Throw if the URLSearchParams has a link to a URL such that users would need to do something like url.searchParams = new URLSearchParams(otherUrl.searchParams)

  3. Make it possible to detach a URLSearchParams from it's URL, e.g. url.searchParams = otherUrl.searchParams.detach() ... which would effectively null out the search params on the otherUrl and break that link.

Of these, number 2 would be my preference.

@domenic
Copy link
Member

domenic commented May 24, 2024

I'm confused by this feature request, and in particular why the search setter doesn't work today.

Given this code:

const usp = new URLSearchParams("foo=bar");
const url = new URL("https://example.com/");
url.search = usp;

you get the desired result: url is modified to have foo=bar search params.

The section "What solutions exist today?" in the OP seems to be implying this isn't good enough. But I can't understand exactly when.

Can you give a concrete example of a URLSearchParams object such that assigning url.search = usp gives the wrong result? And such that setting url.searchParams = usp, using a hypothetical future setter, would give a better result?

All the examples in "How would you solve it?" work today with the search setter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest topic: api
Development

No branches or pull requests

4 participants