240

I have this URL:

site.fwx?position=1&archiveid=5000&columns=5&rows=20&sorting=ModifiedTimeAsc

what I need is to be able to change the 'rows' url param value to something i specify, lets say 10. And if the 'rows' doesn't exist, I need to add it to the end of the url and add the value i've already specified (10).

Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
Sindre Sorhus
  • 62,972
  • 39
  • 168
  • 232
  • 2
    A lightweight, no-plugin answer: http://stackoverflow.com/a/10997390/11236 – ripper234 Oct 03 '12 at 13:45
  • 12
    I can't believe it's 2013 and there's not a better way to do it, like something built into the core browser libraries. – Tyler Collier Oct 25 '13 at 22:21
  • See my answer for a modern solution: http://stackoverflow.com/a/19965480/64949 – Sindre Sorhus Nov 13 '13 at 22:14
  • possible duplicate of [querystring encoding of a javascript object](http://stackoverflow.com/questions/1714786/querystring-encoding-of-a-javascript-object) – Sindre Sorhus Nov 15 '13 at 18:03
  • 8
    @TylerCollier mid-2015 now and still nothing :( – Tejas Manohar Aug 03 '15 at 19:46
  • Already 3rd quarter of 2016, Wondering how Google Maps actually do it, need this functionality for bookmarking. – Aesthetic Sep 08 '16 at 15:55
  • 4
    Seems like we are getting there... https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/URLSearchParams#Browser_compatibility – chris Feb 20 '17 at 16:02
  • https://stackoverflow.com/a/63302942/863110 is the answer now (if you don't care about IE) – Mosh Feu Aug 09 '20 at 11:56
  • 12
    @TylerCollier it's 2021 now and we finally got this :) `const myUrl = new URL("http://www.example.com?columns=5&rows=20");` `myUrl.searchParams.set('rows', 10);` `myUrl.href` will contain updated URL – sprutex Apr 12 '21 at 08:06
  • 2
    based on @sprutex comment , you may replace `http://www.example.com?columns=5&rows=20` with `window.location.href` to make the code more dynamically – Waleed Khaled Oct 11 '21 at 08:24

32 Answers32

134

I've extended Sujoy's code to make up a function.

/**
 * http://stackoverflow.com/a/10997390/11236
 */
function updateURLParameter(url, param, paramVal){
    var newAdditionalURL = "";
    var tempArray = url.split("?");
    var baseURL = tempArray[0];
    var additionalURL = tempArray[1];
    var temp = "";
    if (additionalURL) {
        tempArray = additionalURL.split("&");
        for (var i=0; i<tempArray.length; i++){
            if(tempArray[i].split('=')[0] != param){
                newAdditionalURL += temp + tempArray[i];
                temp = "&";
            }
        }
    }

    var rows_txt = temp + "" + param + "=" + paramVal;
    return baseURL + "?" + newAdditionalURL + rows_txt;
}

Function Calls:

var newURL = updateURLParameter(window.location.href, 'locId', 'newLoc');
newURL = updateURLParameter(newURL, 'resId', 'newResId');

window.history.replaceState('', '', updateURLParameter(window.location.href, "param", "value"));

Updated version that also take care of the anchors on the URL.

function updateURLParameter(url, param, paramVal)
{
    var TheAnchor = null;
    var newAdditionalURL = "";
    var tempArray = url.split("?");
    var baseURL = tempArray[0];
    var additionalURL = tempArray[1];
    var temp = "";

    if (additionalURL) 
    {
        var tmpAnchor = additionalURL.split("#");
        var TheParams = tmpAnchor[0];
            TheAnchor = tmpAnchor[1];
        if(TheAnchor)
            additionalURL = TheParams;

        tempArray = additionalURL.split("&");

        for (var i=0; i<tempArray.length; i++)
        {
            if(tempArray[i].split('=')[0] != param)
            {
                newAdditionalURL += temp + tempArray[i];
                temp = "&";
            }
        }        
    }
    else
    {
        var tmpAnchor = baseURL.split("#");
        var TheParams = tmpAnchor[0];
            TheAnchor  = tmpAnchor[1];

        if(TheParams)
            baseURL = TheParams;
    }

    if(TheAnchor)
        paramVal += "#" + TheAnchor;

    var rows_txt = temp + "" + param + "=" + paramVal;
    return baseURL + "?" + newAdditionalURL + rows_txt;
}
Matthew Wilcoxson
  • 3,432
  • 1
  • 43
  • 48
Adil Malik
  • 6,279
  • 7
  • 48
  • 77
  • I can't seem to get this to work. Here is my code: http://jsfiddle.net/Draven/tTPYL/1/ The URL would look like `http://www.domain.com/index.php?action=my_action&view-all=Yes` and I need to change the "view-all" value. My SO question that was closed: http://stackoverflow.com/questions/13025880/js-append-variable-to-url-without-repeating – Draven Oct 25 '12 at 06:43
  • Are you sure? it worked for me easily. Check it out here: http://jsfiddle.net/mw49a/ – Adil Malik Oct 25 '12 at 10:47
  • 1
    Use "var i=0" instead of "i=0" to prevent creating/modifying i as a global variable. – Jonathan Aquino Sep 05 '14 at 17:34
  • 2
    Couple of other issues with this function: (1) paramVal is not uri-encoded. (2) if paramVal is null, then you get foo=null. It should be foo= (or even better, remove foo completely). – Jonathan Aquino Sep 05 '14 at 17:50
  • I have used this and it works but the answer could do with some explanation as to what is going on, ie. 'if (additionalURL) { tempArray = additionalURL.split("&"); for (i=0; i – Sprose Dec 20 '16 at 09:18
  • @JonathanAquino I also wanted the parameter to be removed when `paramVal === null`. For this effect I've replaced the last 2 lines to the following: `if ( paramVal !== null ) newAdditionalURL += temp + '' + param + '=' + paramVal; return baseURL + '?' + newAdditionalURL;` – caiosm1005 May 15 '17 at 15:51
  • @matthew solution worked for me but i passed param key with encodeURI since param has two strings separated with space .thanks matthew u save my time. var newURL = parameter(window.location.href, encodeURI(key), value); – user961524 May 23 '18 at 07:42
  • It's really good to know my answer is helping people still after years :) – Adil Malik Feb 16 '21 at 14:52
  • *Great answer!* BTW, suggestion, there's no need to concat `""` onto a string: `var rows_txt = temp + "" + param + "=" + paramVal;` – HoldOffHunger May 20 '21 at 12:51
96

I think you want the query plugin.

E.g.:

window.location.search = jQuery.query.set("rows", 10);

This will work regardless of the current state of rows.

1''
  • 26,823
  • 32
  • 143
  • 200
Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539
  • Mofle, that's because the Query plugin uses decodeURIComponent, and decodeURIComponent("%F8") is invalid. – Matthew Flaschen Jul 07 '09 at 09:11
  • 2
    Get that weird stuff out of your URL. Or, in other words, "change your query-string to use only valid UTF-8 characters". :) F8 alone isn't a valid UTF-8 character. – Matthew Flaschen Jul 07 '09 at 09:51
  • Is there a way to retrieve the base url from this plugin? For example, if my URL is 'http://www.youtube.com/watch?v=PZootaxRh3M', get 'http://www.youtube.com/watch' – Matt Norris May 18 '11 at 02:59
  • 3
    @Wraith, you don't need a plugin for that. It's just `window.location.pathname`. – Matthew Flaschen May 18 '11 at 18:43
  • What I'm not working with the url of the page? I want to take any old url and swap out query strings. – Brad Urani May 03 '12 at 21:24
  • @Brad, use `jQuery.query.load` to get a query object. [Demo](http://jsfiddle.net/vZd98/1/). – Matthew Flaschen May 04 '12 at 00:37
  • 2
    @MattNorris You don't need a plugin for this, but correct answer is: window.location.host + window.location.pathname In your case it will be "www.youtube.com/watch" – nktssh Dec 16 '14 at 12:53
82

Quick little solution in pure js, no plugins needed:

function replaceQueryParam(param, newval, search) {
    var regex = new RegExp("([?;&])" + param + "[^&;]*[;&]?");
    var query = search.replace(regex, "$1").replace(/&$/, '');

    return (query.length > 2 ? query + "&" : "?") + (newval ? param + "=" + newval : '');
}

Call it like this:

 window.location = '/mypage' + replaceQueryParam('rows', 55, window.location.search)

Or, if you want to stay on the same page and replace multiple params:

 var str = window.location.search
 str = replaceQueryParam('rows', 55, str)
 str = replaceQueryParam('cols', 'no', str)
 window.location = window.location.pathname + str

edit, thanks Luke: To remove the parameter entirely, pass false or null for the value: replaceQueryParam('rows', false, params). Since 0 is also falsy, specify '0'.

bronson
  • 5,612
  • 3
  • 31
  • 18
  • 2
    also to remove a used parameter from the output do this: str = replaceQueryParam('oldparam',false, str) - basically put a false type value – Luke Wenke Apr 02 '15 at 04:44
  • 1
    has problem, duplication my parameter for no good reason, check out this similar solution http://stackoverflow.com/a/20420424/3160597 – azerafati Aug 05 '15 at 11:12
  • @Bludream that code has been working in production for years. I haven't seen it duplicate a param yet. Can you post a repro or some more constructive info? – bronson Aug 06 '15 at 18:26
  • @Bludream I understand now, it's the script you linked to that was adding duplicate parameters. :) – bronson Dec 10 '15 at 00:32
  • @bronson This doesn't seem to work if you use 0 or false as the newval parameter – dVyper Feb 15 '16 at 11:48
  • 1
    @dVyper correct, a falsy value removes the parameter entirely. Use text '0' instead of integer 0. – bronson Feb 16 '16 at 22:01
  • 1
    This is old but it worked perfectly for me. It's short, clean, easy to modify and gets the job done at last for what I needed. Thanks. – BlueSun3k1 Sep 22 '17 at 14:31
  • Zero is not supported, change "newval ? param" to "newval === null ? param" – ScorpioT1000 May 18 '22 at 05:23
82

To answer my own question 4 years later, after having learned a lot. Especially that you shouldn't use jQuery for everything. I've created a simple module that can parse/stringify a query string. This makes it easy to modify the query string.

You can use query-string as follows:

// parse the query string into an object
var q = queryString.parse(location.search);
// set the `row` property
q.rows = 10;
// convert the object to a query string
// and overwrite the existing query string
location.search = queryString.stringify(q);
Sindre Sorhus
  • 62,972
  • 39
  • 168
  • 232
  • 1
    Wow this is a brilliantly simple solution. Thank you! – jetlej Oct 01 '14 at 00:26
  • This works like a champ! Thank you Sindre (all you gotta do is minify "query-string/index.js" and paste it in bottom of your js) – Ronnie Royston Apr 07 '17 at 19:29
  • 7
    Having an extra library just for that seems like a bit extra... – The Godfather Oct 22 '19 at 15:04
  • 8
    jQuery was too much for 1 function, so instead you used typescript, travis, and several other non-dev dependencies :) – Justin Meiners Jul 06 '20 at 21:47
  • @JustinMeiners Please don't comment if you have nothing useful to contribute to the conversation. TypeScript is not used by this project. Travis is a CI, not a dependency. – Sindre Sorhus Jul 07 '20 at 18:25
  • 3
    @SindreSorhus It was little lighthearted, but I think it's important to keep the complexity of these things in perspective. If you don't feel that's constructive, then ditto. – Justin Meiners Jul 11 '20 at 00:00
77

A modern approach to this is to use native standard based URLSearchParams. It's supported by all major browsers, except for IE where polyfills are available.

const paramsString = "site.fwx?position=1&archiveid=5000&columns=5&rows=20&sorting=ModifiedTimeAsc"
const searchParams = new URLSearchParams(paramsString);
searchParams.set('rows', 10);
console.log(searchParams.toString()); // return modified string.
gotomanners
  • 7,808
  • 1
  • 24
  • 39
Alister
  • 27,049
  • 9
  • 40
  • 35
  • 1
    Would be really nice... but it is not as IE does not support it at all, and using polyfills for such a small thing is totally out of the question. – forsberg Sep 26 '17 at 17:41
  • 2
    this also urlencodes the original paramsString in full, so the result looks like `site.fwx%3Fposition=1&archiveid=5000&columns=5&rows=10&sorting=ModifiedTimeAsc` which is confusing because it's not what you would have built if you did it manually... – Ben Wheeler Oct 24 '18 at 03:14
  • 1
    Would be nice to see an example of how to use it. I mean, how to get params string from the current page and how to set it afterwards – The Godfather Oct 22 '19 at 15:11
  • 3
    @Alister your answer has a bug, `new URLSearchParams("site.fwx?position=1&...` should be `new URLSearchParams("position=1&...` (it only takes the search string, not a path as well). I'd edited to fix but the edit is being rejected? Also @the-godfather `const searchParams = new URLSearchParams(location.search); searchParams.set('rows', 10); location.search = searchParams;` is the extra info you wanted in this answer. – bazzargh Oct 11 '20 at 23:20
  • My favorite solution because it's shortest and native. You can also get params with `searchParams.get('param')`. Works in Node. – The Onin Jan 09 '21 at 06:45
61

Ben Alman has a good jquery querystring/url plugin here that allows you to manipulate the querystring easily.

As requested -

Goto his test page here

In firebug enter the following into the console

jQuery.param.querystring(window.location.href, 'a=3&newValue=100');

It will return you the following amended url string

http://benalman.com/code/test/js-jquery-url-querystring.html?a=3&b=Y&c=Z&newValue=100#n=1&o=2&p=3

Notice the a querystring value for a has changed from X to 3 and it has added the new value.

You can then use the new url string however you wish e.g using document.location = newUrl or change an anchor link etc

Andre Pena
  • 56,650
  • 48
  • 196
  • 243
redsquare
  • 78,161
  • 20
  • 151
  • 159
  • 4
    Isn't it jQuery.param.querystring instead of jQuery.queryString ? – Petr Peller Jan 18 '10 at 11:59
  • 13
    `TypeError: jQuery.param.querystring is not a function` – Tomas Mar 29 '12 at 20:42
  • 1
    To avoir 'TypeError' it should be : jQuery.queryString(window.location.href, 'a=3&newValue=100') – code-gijoe Dec 18 '12 at 19:22
  • 2
    you should call `jQuery.param.querystring`. I guess they have refactored the library. – Will Wu Jan 27 '13 at 09:18
  • Neither of these functions exist any more. You want to update window.location.search manually. It gets more difficult if you don't want the page to repaint, since this will cause a page change. – monokrome Jul 18 '13 at 19:40
  • The Ben Alman jQuery BBQ plugin seems to be abandoned. We are considering using [Query String](https://github.com/sindresorhus/query-string) as mentioned in the [accepted answer](http://stackoverflow.com/a/19965480/1191545). – Brylie Christopher Oxley Nov 18 '15 at 10:44
  • @Brylie yeah jquery + its plugins are becoming obsolete – redsquare Nov 19 '15 at 17:28
38

This is the modern way to change URL parameters:

function setGetParam(key,value) {
  if (history.pushState) {
    var params = new URLSearchParams(window.location.search);
    params.set(key, value);
    var newUrl = window.location.origin 
          + window.location.pathname 
          + '?' + params.toString();
    window.history.pushState({path:newUrl},'',newUrl);
  }
}
TjerkW
  • 2,086
  • 21
  • 26
  • 3
    This solution is currently not supported in Internet Explorer 11: https://caniuse.com/#search=URLSearchParams – ˈvɔlə Dec 05 '19 at 11:16
  • The same respons was replied a half year before you by @Alister – FantomX1 May 13 '20 at 19:31
  • @WoIIe Using URLSearchParams is the cleanest solution. IMO if business requirements still demand IE11 support in 2020. It's time to find a new business to work for. – Philip Attisano Jul 24 '20 at 10:41
  • 1
    Come on. Businesses don't determine their user base, and a lot of the people still using IE11 are poor and elderly. Literally the sort of people for whom we should NOT be relegating into a bucket of acceptably broken experiences. – Dtipson Aug 31 '20 at 16:30
  • use `document.title` for history title – Amir2mi Jun 28 '21 at 08:25
  • 3
    "Internet Explorer will be retired on June 15, 2022" https://blogs.windows.com/windowsexperience/2021/05/19/the-future-of-internet-explorer-on-windows-10-is-in-microsoft-edge/ – Justin Breen Sep 27 '21 at 16:50
  • Nice one. You can change `window.location.protocol + "//" + window.location.host + window.location.pathname` simply with `window.location.origin` – Nadav Jun 23 '22 at 22:34
  • works, nice one. – mohitesachin217 Mar 13 '23 at 06:54
28

you can do it via normal JS also

var url = document.URL
var newAdditionalURL = "";
var tempArray = url.split("?");
var baseURL = tempArray[0];
var aditionalURL = tempArray[1]; 
var temp = "";
if(aditionalURL)
{
var tempArray = aditionalURL.split("&");
for ( var i in tempArray ){
    if(tempArray[i].indexOf("rows") == -1){
            newAdditionalURL += temp+tempArray[i];
                temp = "&";
            }
        }
}
var rows_txt = temp+"rows=10";
var finalURL = baseURL+"?"+newAdditionalURL+rows_txt;
Jasper Kennis
  • 3,225
  • 6
  • 41
  • 74
Posto
  • 7,362
  • 7
  • 44
  • 61
  • Nice! I took this and modified into a function. You send in the current url, the parameter name you're looking for, the new value, and a bool telling it if you want to add the parameter to the query string if I don't find it in there currently. Function returns the modified url. – Gromer May 03 '12 at 21:30
  • Gormer, you must share that function with others :) – Adil Malik Jun 12 '12 at 12:07
  • Awesome snippet. I too turned it into a function for my own use case. Thanks for sharing! +1 – robabby Sep 19 '12 at 18:34
22

Use URLSearchParams to check, get and set the parameters value into URL

Here is the example to get the current URL and set new parameter and update the URL or reload the page as per your needs

var rows = 5; // value that you want to set
var url = new URL(window.location);
(url.searchParams.has('rows') ? url.searchParams.set('rows', rows) : url.searchParams.append('rows', rows));

url.search = url.searchParams;
url        = url.toString();

// if you want to append into URL without reloading the page
history.pushState({}, null, url);

// want to reload the window with a new param
window.location = url;
Onkar
  • 2,409
  • 2
  • 11
  • 14
13

2020 Solution: sets the variable or removes iti if you pass null or undefined to the value.

var setSearchParam = function(key, value) {
    if (!window.history.pushState) {
        return;
    }

    if (!key) {
        return;
    }

    var url = new URL(window.location.href);
    var params = new window.URLSearchParams(window.location.search);
    if (value === undefined || value === null) {
        params.delete(key);
    } else {
        params.set(key, value);
    }

    url.search = params;
    url = url.toString();
    window.history.replaceState({url: url}, null, url);
}
Alper Ebicoglu
  • 8,884
  • 1
  • 49
  • 55
  • Note that `URLSearchParams` does not work in the latest versions of all major browsers (2020) – Oliver Schimmer Mar 27 '20 at 15:53
  • still available in major browsers: https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams , https://googlechrome.github.io/samples/urlsearchparams/index.html – Alper Ebicoglu Mar 31 '20 at 07:10
  • 1
    It's supported in all major browsers except IE11: https://caniuse.com/#search=URLSearchParams – Luis Paulo Lohmann Apr 15 '20 at 12:29
  • 2
    Even if it started to be supported, the same answer with URLSearchParams was answered in this question at least 3 times already on answered Jan 15 '17 at 15:24, answered Jun 14 '18 at 15:54 and answered Mar 1 '19 at 12:46 , as if nobody of you was reading replies before posting – FantomX1 May 13 '20 at 19:39
  • 1
    all posts have minor issues that needs to be solved. so let the users vote and pick the best one. – Alper Ebicoglu May 21 '20 at 13:07
  • 1
    Why is there a need to check `pushState`? Is it to check if this is supported? – M3RS Jun 29 '20 at 17:48
10

Would a viable alternative to String manipulation be to set up an html form and just modify the value of the rows element?

So, with html that is something like

<form id='myForm' target='site.fwx'>
    <input type='hidden' name='position' value='1'/>
    <input type='hidden' name='archiveid' value='5000'/>
    <input type='hidden' name='columns' value='5'/>
    <input type='hidden' name='rows' value='20'/>
    <input type='hidden' name='sorting' value='ModifiedTimeAsc'/>
</form>

With the following JavaScript to submit the form

var myForm = document.getElementById('myForm');
myForm.rows.value = yourNewValue;
myForm.submit();

Probably not suitable for all situations, but might be nicer than parsing the URL string.

Harry Lime
  • 29,476
  • 4
  • 31
  • 37
10

URL query parameters can be easily modified using URLSearchParams and History interfaces:

// Construct URLSearchParams object instance from current URL querystring.
var queryParams = new URLSearchParams(window.location.search);
 
// Set new or modify existing parameter value. 
//queryParams.set("myParam", "myValue");
queryParams.set("rows", "10");
 
// Replace current querystring with the new one.
history.replaceState(null, null, "?"+queryParams.toString());

Alternatively instead of modifying current history entry using replaceState() we can use pushState() method to create a new one:

history.pushState(null, null, "?"+queryParams.toString());

https://zgadzaj.com/development/javascript/how-to-change-url-query-parameter-with-javascript-only

Waruna Manjula
  • 3,067
  • 1
  • 34
  • 33
7

You can use this my library to do the job: https://github.com/Mikhus/jsurl

var url = new Url('site.fwx?position=1&archiveid=5000&columns=5&rows=20&sorting=ModifiedTimeAsc');
url.query.rows = 10;
alert( url);
Mikhus
  • 1,069
  • 11
  • 8
7

Consider this one:

const myUrl = new URL("http://www.example.com?columns=5&rows=20");
myUrl.searchParams.set('rows', 10);
console.log(myUrl.href); // http://www.example.com?columns=5&rows=10
myUrl.searchParams.set('foo', 'bar'); // add new param
console.log(myUrl.href); // http://www.example.com?columns=5&rows=10&foo=bar

It will do exactly the same thing you required. Please note URL must have correct format. In your example you have to specify protocol (either http or https)

sprutex
  • 980
  • 12
  • 12
3

Using javascript URL:

var url = new URL(window.location);
(url.searchParams.has('rows') ? url.searchParams.set('rows', rows) : url.searchParams.append('rows', rows));
window.location = url;
Gerard Carbó
  • 1,775
  • 18
  • 16
3
var url = new URL(window.location.href);
var search_params = url.searchParams;
search_params.set("param", value);
url.search = search_params.toString();
var new_url = url.pathname + url.search;
window.history.replaceState({}, '', new_url);
Brahim SLIMANI
  • 310
  • 1
  • 8
3

I wrote a little helper function that works with any select. All you need to do is add the class "redirectOnChange" to any select element, and this will cause the page to reload with a new/changed querystring parameter, equal to the id and value of the select, e.g:

<select id="myValue" class="redirectOnChange"> 
    <option value="222">test222</option>
    <option value="333">test333</option>
</select>

The above example would add "?myValue=222" or "?myValue=333" (or using "&" if other params exist), and reload the page.

jQuery:

$(document).ready(function () {

    //Redirect on Change
    $(".redirectOnChange").change(function () {
        var href = window.location.href.substring(0, window.location.href.indexOf('?'));
        var qs = window.location.href.substring(window.location.href.indexOf('?') + 1, window.location.href.length);
        var newParam = $(this).attr("id") + '=' + $(this).val();

        if (qs.indexOf($(this).attr("id") + '=') == -1) {
            if (qs == '') {
                qs = '?'
            }
            else {
                qs = qs + '&'
            }
            qs = qs + newParam;

        }
        else {
            var start = qs.indexOf($(this).attr("id") + "=");
            var end = qs.indexOf("&", start);
            if (end == -1) {
                end = qs.length;
            }
            var curParam = qs.substring(start, end);
            qs = qs.replace(curParam, newParam);
        }
        window.location.replace(href + '?' + qs);
    });
});
Paul Grimshaw
  • 19,894
  • 6
  • 40
  • 59
2

Here I have taken Adil Malik's answer and fixed the 3 issues I identified with it.

/**
 * Adds or updates a URL parameter.
 *
 * @param {string} url  the URL to modify
 * @param {string} param  the name of the parameter
 * @param {string} paramVal  the new value for the parameter
 * @return {string}  the updated URL
 */
self.setParameter = function (url, param, paramVal){
  // http://stackoverflow.com/a/10997390/2391566
  var parts = url.split('?');
  var baseUrl = parts[0];
  var oldQueryString = parts[1];
  var newParameters = [];
  if (oldQueryString) {
    var oldParameters = oldQueryString.split('&');
    for (var i = 0; i < oldParameters.length; i++) {
      if(oldParameters[i].split('=')[0] != param) {
        newParameters.push(oldParameters[i]);
      }
    }
  }
  if (paramVal !== '' && paramVal !== null && typeof paramVal !== 'undefined') {
    newParameters.push(param + '=' + encodeURI(paramVal));
  }
  if (newParameters.length > 0) {
    return baseUrl + '?' + newParameters.join('&');
  } else {
    return baseUrl;
  }
}
Jonathan Aquino
  • 3,780
  • 1
  • 18
  • 19
2

In the URLSearchParams documentation, there's a very clean way of doing this, without affecting the history stack.

// URL: https://example.com?version=1.0
const params = new URLSearchParams(location.search);
params.set('version', 2.0);

window.history.replaceState({}, '', `${location.pathname}?${params}`);
// URL: https://example.com?version=2.0

Similarily, to remove a parameter

params.delete('version')
window.history.replaceState({}, '', `${location.pathname}?${params}`);
// URL: https://example.com?
2

let url= new URL("https://example.com/site.fwx?position=1&archiveid=5000&columns=5&rows=20&sorting=ModifiedTimeAsc")
url.searchParams.set('rows', 10)
console.log(url.toString())
Fawaz Ahmed
  • 1,082
  • 2
  • 14
  • 18
1

Here is what I do. Using my editParams() function, you can add, remove, or change any parameter, then use the built in replaceState() function to update the URL:

window.history.replaceState('object or string', 'Title', 'page.html' + editParams('sorting', ModifiedTimeAsc));


// background functions below:

// add/change/remove URL parameter
// use a value of false to remove parameter
// returns a url-style string
function editParams (key, value) {
  key = encodeURI(key);

  var params = getSearchParameters();

  if (Object.keys(params).length === 0) {
    if (value !== false)
      return '?' + key + '=' + encodeURI(value);
    else
      return '';
  }

  if (value !== false)
    params[key] = encodeURI(value);
  else
    delete params[key];

  if (Object.keys(params).length === 0)
    return '';

  return '?' + $.map(params, function (value, key) {
    return key + '=' + value;
  }).join('&');
}

// Get object/associative array of URL parameters
function getSearchParameters () {
  var prmstr = window.location.search.substr(1);
  return prmstr !== null && prmstr !== "" ? transformToAssocArray(prmstr) : {};
}

// convert parameters from url-style string to associative array
function transformToAssocArray (prmstr) {
  var params = {},
      prmarr = prmstr.split("&");

  for (var i = 0; i < prmarr.length; i++) {
    var tmparr = prmarr[i].split("=");
    params[tmparr[0]] = tmparr[1];
  }
  return params;
}
Bobb Fwed
  • 317
  • 3
  • 6
1

My solution:

const setParams = (data) => {
    if (typeof data !== 'undefined' && typeof data !== 'object') {
        return
    }

    let url = new URL(window.location.href)
    const params = new URLSearchParams(url.search)

    for (const key of Object.keys(data)) {
        if (data[key] == 0) {
            params.delete(key)
        } else {
            params.set(key, data[key])
        }
    }

    url.search = params
    url = url.toString()
    window.history.replaceState({ url: url }, null, url)
}

Then just call "setParams" and pass an object with data you want to set.

Example:

$('select').on('change', e => {
    const $this = $(e.currentTarget)
    setParams({ $this.attr('name'): $this.val() })
})

In my case I had to update a html select input when it changes and if the value is "0", remove the parameter. You can edit the function and remove the parameter from the url if the object key is "null" as well.

Hope this helps yall

Benjamin
  • 19
  • 1
  • there are already 2 same answers with URLSearchParams before you, as if nobody of you really read answers. Posted on answered Jan 15 '17 at 15:24 , answered Jun 14 '18 at 15:54 – FantomX1 May 13 '20 at 19:38
1

If you want to change the url in address bar:

const search = new URLSearchParams(location.search);
search.set('rows', 10);
location.search = search.toString();

Note, changing location.search reloads the page.

Klesun
  • 12,280
  • 5
  • 59
  • 52
1

Here is a simple solution using the query-string library.

const qs = require('query-string')
function addQuery(key, value) {
  const q = qs.parse(location.search)
  const url = qs.stringifyUrl(
    {
      url: location.pathname,
      query: {
      ...q,
      [key]: value,
      },
    },
    { skipEmptyString: true }
  );
  window.location.href = url
  // if you are using Turbolinks
  // add this: Turbolinks.visit(url)
}
// Usage
addQuery('page', 2)

If you are using react without react-router

export function useAddQuery() {
  const location = window.location;
  const addQuery = useCallback(
    (key, value) => {
      const q = qs.parse(location.search);
      const url = qs.stringifyUrl(
        {
          url: location.pathname,
          query: {
            ...q,
            [key]: value,
          },
        },
        { skipEmptyString: true }
      );
      window.location.href = url
    },
    [location]
  );

  return { addQuery };
}
// Usage
const { addQuery } = useAddQuery()
addQuery('page', 2)

If you are using react with react-router

export function useAddQuery() {
  const location = useLocation();
  const history = useHistory();

  const addQuery = useCallback(
    (key, value) => {
      let pathname = location.pathname;
      let searchParams = new URLSearchParams(location.search);
      searchParams.set(key, value);
      history.push({
        pathname: pathname,
        search: searchParams.toString()
      });
    },
    [location, history]
  );

  return { addQuery };
}

// Usage
const { addQuery } = useAddQuery()
addQuery('page', 2)

PS: qs is the import from query-string module.

Abeid Ahmed
  • 315
  • 1
  • 5
  • 15
0

Another variation on Sujoy's answer. Just changed the variable names & added a namespace wrapper:

window.MyNamespace = window.MyNamespace  || {};
window.MyNamespace.Uri = window.MyNamespace.Uri || {};

(function (ns) {

    ns.SetQueryStringParameter = function(url, parameterName, parameterValue) {

        var otherQueryStringParameters = "";

        var urlParts = url.split("?");

        var baseUrl = urlParts[0];
        var queryString = urlParts[1];

        var itemSeparator = "";
        if (queryString) {

            var queryStringParts = queryString.split("&");

            for (var i = 0; i < queryStringParts.length; i++){

                if(queryStringParts[i].split('=')[0] != parameterName){

                    otherQueryStringParameters += itemSeparator + queryStringParts[i];
                    itemSeparator = "&";
                }
            }
        }

        var newQueryStringParameter = itemSeparator + parameterName + "=" + parameterValue;

        return baseUrl + "?" + otherQueryStringParameters + newQueryStringParameter;
    };

})(window.MyNamespace.Uri);

Useage is now:

var changedUrl = MyNamespace.Uri.SetQueryStringParameter(originalUrl, "CarType", "Ford");
Appetere
  • 6,003
  • 7
  • 35
  • 46
0

I too have written a library for getting and setting URL query parameters in JavaScript.

Here is an example of its usage.

var url = Qurl.create()
  , query
  , foo
  ;

Get query params as an object, by key, or add/change/remove.

// returns { foo: 'bar', baz: 'qux' } for ?foo=bar&baz=qux
query = url.query();

// get the current value of foo
foo = url.query('foo');

// set ?foo=bar&baz=qux
url.query('foo', 'bar');
url.query('baz', 'qux');

// unset foo, leaving ?baz=qux
url.query('foo', false); // unsets foo
rb-
  • 2,315
  • 29
  • 41
0

I was looking for the same thing and found: https://github.com/medialize/URI.js which is quite nice :)

-- Update

I found a better package: https://www.npmjs.org/package/qs it also deals with arrays in get params.

Chris
  • 8,168
  • 8
  • 36
  • 51
0

No library, using URL() WebAPI (https://developer.mozilla.org/en-US/docs/Web/API/URL)

function setURLParameter(url, parameter, value) {
    let url = new URL(url);
    if (url.searchParams.get(parameter) === value) {
        return url;
    }
    url.searchParams.set(parameter, value);
    return url.href;
}

This doesn't work on IE: https://developer.mozilla.org/en-US/docs/Web/API/URL#Browser_compatibility

Alexander
  • 80
  • 1
  • 10
-1

I know this is an old question. I have enhanced the function above to add or update query params. Still a pure JS solution only.

                      function addOrUpdateQueryParam(param, newval, search) {

                        var questionIndex = search.indexOf('?');

                        if (questionIndex < 0) {
                            search = search + '?';
                            search = search + param + '=' + newval;
                            return search;
                        }

                        var regex = new RegExp("([?;&])" + param + "[^&;]*[;&]?");
                        var query = search.replace(regex, "$1").replace(/&$/, '');

                        var indexOfEquals = query.indexOf('=');

                        return (indexOfEquals >= 0 ? query + '&' : query + '') + (newval ? param + '=' + newval : '');
                    }
-1

my function support removing param

function updateURLParameter(url, param, paramVal, remove = false) {
        var newAdditionalURL = '';
        var tempArray = url.split('?');
        var baseURL = tempArray[0];
        var additionalURL = tempArray[1];
        var rows_txt = '';

        if (additionalURL)
            newAdditionalURL = decodeURI(additionalURL) + '&';

        if (remove)
            newAdditionalURL = newAdditionalURL.replace(param + '=' + paramVal, '');
        else
            rows_txt = param + '=' + paramVal;

        window.history.replaceState('', '', (baseURL + "?" + newAdditionalURL + rows_txt).replace('?&', '?').replace('&&', '&').replace(/\&$/, ''));
    }
-1

I just wrote a simple module to deal with reading and updating the current url query params.

Example usage:

import UrlParams from './UrlParams'

UrlParams.remove('foo') //removes all occurences of foo=?
UrlParams.set('foo', 'bar') //set all occurences of foo equal to bar
UrlParams.add('foo', 'bar2') //add bar2 to foo result: foo=bar&foo=bar2
UrlParams.get('foo') //returns bar
UrlParams.get('foo', true) //returns [bar, bar2]

Here is my code named UrlParams.(js/ts):

class UrlParams {

    /**
     * Get params from current url
     * 
     * @returns URLSearchParams
     */
    static getParams(){
        let url = new URL(window.location.href)
        return new URLSearchParams(url.search.slice(1))
    }

    /**
     * Update current url with params
     * 
     * @param params URLSearchParams
     */
    static update(params){
        if(`${params}`){
            window.history.replaceState({}, '', `${location.pathname}?${params}`)
        } else {
            window.history.replaceState({}, '', `${location.pathname}`)
        }
    }

    /**
     * Remove key from url query
     * 
     * @param param string
     */
    static remove(param){
        let params = this.getParams()
        if(params.has(param)){
            params.delete(param)
            this.update(params)
        }
    }

    /**
     * Add key value pair to current url
     * 
     * @param key string
     * @param value string
     */
    static add(key, value){
        let params = this.getParams()
        params.append(key, value)
        this.update(params)
    }

    /**
     * Get value or values of key
     * 
     * @param param string
     * @param all string | string[]
     */
    static get(param, all=false){
        let params = this.getParams()
        if(all){
            return params.getAll(param)
        }
        return params.get(param)
    }

    /**
     * Set value of query param
     * 
     * @param key string
     * @param value string
     */
    static set(key, value){
        let params = this.getParams()
        params.set(key, value)
        this.update(params)
    }

}
export default UrlParams
export { UrlParams }
Dieter Gribnitz
  • 5,062
  • 2
  • 41
  • 38
  • There are already 4 same replies as you mentioned posted on, answered Jan 15 '17 at 15:24 , answered Jun 14 '18 at 15:54 , answered Mar 1 '19 at 12:46 and answered Jun 14 '19 at 7:20, as if nobody really of you read answers before posting – FantomX1 May 13 '20 at 19:36
-2
     // usage: clear ; cd src/js/node/js-unit-tests/01-set-url-param ; npm test ; cd -
     // prereqs: , nodejs , mocha
     // URI = scheme:[//authority]path[?paramName1=paramValue1&paramName2=paramValue2][#fragment]
     // call by: uri = uri.setUriParam("as","md")
     String.prototype.setUriParam = function (paramName, paramValue) {
        var uri = this
        var fragment = ( uri.indexOf('#') === -1 ) ? '' : uri.split('#')[1]
        uri = ( uri.indexOf('#') === -1 ) ? uri : uri.split('#')[0]
        if ( uri.indexOf("?") === -1 ) { uri = uri + '?&' }
        uri = uri.replace ( '?' + paramName , '?&' + paramName)
        var toRepl = (paramValue != null) ? ('$1' + paramValue) : ''
        var toSrch = new RegExp('([&]' + paramName + '=)(([^&#]*)?)')
        uri = uri.replace(toSrch,toRepl)
        if (uri.indexOf(paramName + '=') === -1 && toRepl != '' ) {
           var ampersandMayBe = uri.endsWith('&') ? '' : '&'
           uri = uri + ampersandMayBe + paramName + "=" + String(paramValue)
        }
        uri = ( fragment.length == 0 ) ? uri : (uri+"#"+fragment) //may-be re-add the fragment
        return uri
     }

     var assert = require('assert');
     describe('replacing url param value', function () {

        // scheme://authority/path[?p1=v1&p2=v2#fragment
        // a clean url
        it('http://org.com/path -> http://org.com/path?&prm=tgt_v', function (){
           var uri = 'http://site.eu:80/qto/view/devops_guide_doc'
           var uriExpected = 'http://site.eu:80/qto/view/devops_guide_doc?&bid=10'
           var uriActual = uri.setUriParam("bid",10)
           assert.equal(uriActual, uriExpected);
        });

        // has the url param existing after the ? with num value
        it('http://org.com/path?prm=src_v -> http://org.com/path?&prm=tgt_v', function (){
           var uri = 'http://site.eu:80/qto/view/devops_guide_doc?bid=57'
           var uriExpected = 'http://site.eu:80/qto/view/devops_guide_doc?&bid=10'
           var uriActual = uri.setUriParam("bid",10)
           assert.equal(uriActual, uriExpected);
        });

        // has the url param existing after the ? but string value
        it('http://org.com/path?prm=src_v -> http://org.com/path?&prm=tgt_v', function (){
           var uri = 'http://site.eu:80/qto/view/devops_guide_doc?bid=boo-bar'
           var uriExpected = 'http://site.eu:80/qto/view/devops_guide_doc?&bid=boo-bar-baz'
           var uriActual = uri.setUriParam("bid","boo-bar-baz")
           assert.equal(uriActual, uriExpected);
        });

        // has the url param existing after the ?& but string value
        it('http://org.com/path?&prm=src_v -> http://org.com/path?&prm=tgt_v', function (){
           var uri = 'http://site.eu:80/qto/view/devops_guide_doc?&bid=5'
           var uriExpected = 'http://site.eu:80/qto/view/devops_guide_doc?&bid=10'
           var uriActual = uri.setUriParam("bid",10)
           assert.equal(uriActual, uriExpected);
        });

        // has the url param existing after the ? with other param
        it('http://org.com/path?prm=src_v&other_p=other_v -> http://org.com/path?&prm=tgt_v&other_p=other_v', function (){
           var uri = 'http://site.eu:80/qto/view/devops_guide_doc?bid=5&other_p=other_v'
           var uriExpected = 'http://site.eu:80/qto/view/devops_guide_doc?&bid=10&other_p=other_v'
           var uriActual = uri.setUriParam("bid",10)
           assert.equal(uriActual, uriExpected);
        });

        // has the url param existing after the ?& with other param
        it('http://org.com/path?&prm=src_v&other_p=other_v -> http://org.com/path?&prm=tgt_v&other_p=other_v', function (){
           var uri = 'http://site.eu:80/qto/view/devops_guide_doc?&bid=5&other_p&other_v'
           var uriExpected = 'http://site.eu:80/qto/view/devops_guide_doc?&bid=10&other_p&other_v'
           var uriActual = uri.setUriParam("bid",10)
           assert.equal(uriActual, uriExpected);
        });

        // has the url param existing after the ? with other param with fragment
        it('http://org.com/path?prm=src_v&other_p=other_v#f -> http://org.com/path?&prm=tgt_v&other_p=other_v#f', function (){
           var uri = 'http://site.eu:80/qto/view/devops_guide_doc?bid=5&other_p=other_v#f'
           var uriExpected = 'http://site.eu:80/qto/view/devops_guide_doc?&bid=10&other_p=other_v#f'
           var uriActual = uri.setUriParam("bid",10)
           assert.equal(uriActual, uriExpected);
        });

        // has the url param existing after the ?& with other param with fragment
        it('http://org.com/path?&prm=src_v&other_p=other_v#f -> http://org.com/path?&prm=tgt_v&other_p=other_v#f', function (){
           var uri = 'http://site.eu:80/qto/view/devops_guide_doc?&bid=5&other_p&other_v#f'
           var uriExpected = 'http://site.eu:80/qto/view/devops_guide_doc?&bid=10&other_p&other_v#f'
           var uriActual = uri.setUriParam("bid",10)
           assert.equal(uriActual, uriExpected);
        });

        // remove the param-name , param-value pair
        it('http://org.com/path?prm=src_v&other_p=other_v#f -> http://org.com/path?&prm=tgt_v&other_p=other_v#f', function (){
           var uri = 'http://site.eu:80/qto/view/devops_guide_doc?bid=5&other_p=other_v#f'
           var uriExpected = 'http://site.eu:80/qto/view/devops_guide_doc?&other_p=other_v#f'
           var uriActual = uri.setUriParam("bid",null)
           assert.equal(uriActual, uriExpected);
        });

        // remove the param-name , param-value pair
        it('http://org.com/path?&prm=src_v&other_p=other_v#f -> http://org.com/path?&prm=tgt_v&other_p=other_v#f', function (){
           var uri = 'http://site.eu:80/qto/view/devops_guide_doc?&bid=5&other_p=other_v#f'
           var uriExpected = 'http://site.eu:80/qto/view/devops_guide_doc?&other_p=other_v#f'
           var uriActual = uri.setUriParam("bid",null)
           assert.equal(uriActual, uriExpected);
        });

        // add a new param name , param value pair
        it('http://org.com/path?prm=src_v&other_p=other_v#f -> http://org.com/path?&prm=tgt_v&other_p=other_v#f', function (){
           var uri = 'http://site.eu:80/qto/view/devops_guide_doc?&other_p=other_v#f'
           var uriExpected = 'http://site.eu:80/qto/view/devops_guide_doc?&other_p=other_v&bid=foo-bar#f'
           var uriActual = uri.setUriParam("bid","foo-bar")
           assert.equal(uriActual, uriExpected);
        });

     });
Yordan Georgiev
  • 5,114
  • 1
  • 56
  • 53