505

With javascript how can I add a query string parameter to the url if not present or if it present, update the current value? I am using jquery for my client side development.

4
  • 1
    It seems like I've written the "parseQueryString" function in JavaScript about 100 times over my career. It's not hard. Key points, String#split takes a second parameter for max splits. jQuery's map will also be helpful. Commented May 14, 2011 at 0:52
  • This SO post also has many solutions stackoverflow.com/questions/1090948/… Commented Mar 7, 2013 at 20:08
  • 2
    Some people are taking this question to mean "how to change the URL in the address bar" and others "how to change any URL variable" Commented Jul 10, 2016 at 11:55
  • possible duplicate of stackoverflow.com/questions/486896/… Commented Sep 27, 2019 at 1:10

31 Answers 31

522

I wrote the following function which accomplishes what I want to achieve:

function updateQueryStringParameter(uri, key, value) {
  var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
  var separator = uri.indexOf('?') !== -1 ? "&" : "?";
  if (uri.match(re)) {
    return uri.replace(re, '$1' + key + "=" + value + '$2');
  }
  else {
    return uri + separator + key + "=" + value;
  }
}
Sign up to request clarification or add additional context in comments.

16 Comments

This answer doesn't work when there is a hash in the URI - query strings must be placed before the hash, else they don't get sent to the server. jsfiddle.net/4yXzR
Limit separator variable scoping to local function by adding var just before separator declaration.
Nice! @greg: you are right - see my answer for a variant which should cope with hash tags
I think, you should add value = encodeURIComponent(value); in the first line, otherwise line breaks are not escaped correctly.
This will take care of the hash as well: gist.github.com/niyazpk/f8ac616f181f6042d1e0
|
408

Update (2020): URLSearchParams is now supported by all modern browsers.

The URLSearchParams utility can be useful for this in combination with window.location.search. For example:

if ('URLSearchParams' in window) {
    var searchParams = new URLSearchParams(window.location.search);
    searchParams.set("foo", "bar");
    window.location.search = searchParams.toString();
}

Now foo has been set to bar regardless of whether or not it already existed.

However, the above assignment to window.location.search will cause a page load, so if that's not desirable use the History API as follows:

if ('URLSearchParams' in window) {
  const url = new URL(window.location)
  url.searchParams.set("foo", "bar")
  history.pushState(null, '', url);
}

Now you don't need to write your own regex or logic to handle the possible existence of query strings.

4 Comments

polly fill, is not good, Unable to set property '__URLSearchParams__:0.8503766759030615' of undefined or null reference on ie11 you get that error. it's not a pollyfill if it doesn't work as a fallback.
Update 2019: Browser support is now good for most browsers except IE and some small mobile browsers. New pollyfill of ungap easily covers that: github.com/ungap/url-search-params
Perfect answer, however it doesnt handle usecase when hashtag is present in the url. Simple append of hash to the end of newRelativePathQuery does the trick: var newRelativePathQuery = window.location.pathname + '?' + searchParams.toString() + window.location.hash;
I find URL easier to use than URLSearchParams const url = new URL(window.location); url.searchParams.set("foo", "bar"); window.location = url;
195

I have expanded the solution and combined it with another that I found to replace/update/remove the querystring parameters based on the users input and taking the urls anchor into consideration.

Not supplying a value will remove the parameter, supplying one will add/update the parameter. If no URL is supplied, it will be grabbed from window.location

function UpdateQueryString(key, value, url) {
    if (!url) url = window.location.href;
    var re = new RegExp("([?&])" + key + "=.*?(&|#|$)(.*)", "gi"),
        hash;

    if (re.test(url)) {
        if (typeof value !== 'undefined' && value !== null) {
            return url.replace(re, '$1' + key + "=" + value + '$2$3');
        } 
        else {
            hash = url.split('#');
            url = hash[0].replace(re, '$1$3').replace(/(&|\?)$/, '');
            if (typeof hash[1] !== 'undefined' && hash[1] !== null) {
                url += '#' + hash[1];
            }
            return url;
        }
    }
    else {
        if (typeof value !== 'undefined' && value !== null) {
            var separator = url.indexOf('?') !== -1 ? '&' : '?';
            hash = url.split('#');
            url = hash[0] + separator + key + '=' + value;
            if (typeof hash[1] !== 'undefined' && hash[1] !== null) {
                url += '#' + hash[1];
            }
            return url;
        }
        else {
            return url;
        }
    }
}

10 Comments

Just checking the 'truthiness' of value will cause this to remove variables from the querystring when you set their value to 0. so instead of if (value) {} you should use if (typeOf value !== 'undefined' && value !== null) {}
@YonatanKarni that's interesting, my quick test worked but I'll revert it to that until I have time to look into it thanks
I don't see the declaration of "var hash", where is it?
oh, I guess you can do var re = foo, hash; ? it's not very clear/readable though, please put the hash var the first, before re
A linters worst nightmare :/
|
59

You can use the browser's native URL API to do this in a very simple way, where key and value are your parameter name and parameter value respectively.

const url = new URL(location.href);
url.searchParams.set(key, value);

This will preserve everything about the URL and only change or add the one query param.

You can then do whatever you want with the url object. Examples:

// Log the URL string.
console.log(url.href);

// Go to the URL.
location.assign(url);

// Go to the URL, but overwrite this history entry.
location.replace(url);

// Same as `location.assign` without reloading.
history.pushState(null, '', url);

// Same as `location.replace` without reloading.
history.replaceState(null, '', url);

Comments

46

Based on @amateur's answer (and now incorporating the fix from @j_walker_dev comment), but taking into account the comment about hash tags in the url I use the following:

function updateQueryStringParameter(uri, key, value) {
  var re = new RegExp("([?&])" + key + "=.*?(&|#|$)", "i");
  if (uri.match(re)) {
    return uri.replace(re, '$1' + key + "=" + value + '$2');
  } else {
    var hash =  '';
    if( uri.indexOf('#') !== -1 ){
        hash = uri.replace(/.*#/, '#');
        uri = uri.replace(/#.*/, '');
    }
    var separator = uri.indexOf('?') !== -1 ? "&" : "?";    
    return uri + separator + key + "=" + value + hash;
  }
}

Edited to fix [?|&] in regex which should of course be [?&] as pointed out in the comments

Edit: Alternative version to support removing URL params as well. I have used value === undefined as the way to indicate removal. Could use value === false or even a separate input param as wanted.

function updateQueryStringParameter(uri, key, value) {
  var re = new RegExp("([?&])" + key + "=.*?(&|#|$)", "i");
  if( value === undefined ) {
    if (uri.match(re)) {
    return uri.replace(re, '$1$2').replace(/[?&]$/, '').replaceAll(/([?&])&+/g, '$1').replace(/[?&]#/, '#');
  } else {
    return uri;
  }
  } else {
    if (uri.match(re)) {
      return uri.replace(re, '$1' + key + "=" + value + '$2');
  } else {
    var hash =  '';
    if( uri.indexOf('#') !== -1 ){
        hash = uri.replace(/.*#/, '#');
        uri = uri.replace(/#.*/, '');
    }
    var separator = uri.indexOf('?') !== -1 ? "&" : "?";    
    return uri + separator + key + "=" + value + hash;
    }
  }
}

See it in action at https://jsfiddle.net/cdt16wex/

12 Comments

Much cleaner. FYI for angular ui-router users who can have "?" in the hash as well. Moving the var separator line to right above the return fixes a bug with "/app#/cool?fun=true". This would choose a "&" as the separator even though there are no real query string params yet. Only client ones.
As pointed out in comments on other answers, [?|&] should be just [?&] (otherwise will match |).
Yeah, "([?|&])" is not good. Please fix this as either var re = new RegExp("(?|&)" + key + "=.*?(&|#|$)", "i"); or var re = new RegExp("([?&])" + key + "=.*?(&|#|$)", "i"); (a nice extension in other ways!)
ok, sorry, var re = new RegExp("(?|&)" + key + "=.*?(&|#|$)", "i"); doesn't work, the second one does
Thanks, great edit. In the JSFiddle if I repeatedly remove and add parameters eventually the URL ends up looking like this: https://www.example.com/?&&&&#bazAnd if I remove just the foo parameter I get this: https://www.example.com/?&bar=2#baz with both ? and & in there even though there's only one parameter.
|
25

Thanks to modern javascript, node.js and browsers support, we can get out of 3rd-party library whirlpool (jquery, query-string etc.) and DRY ourselves.

Here are javascript(node.js) and typescript version for a function that adds or updates query params of given url:

Javascript

const getUriWithParam = (baseUrl, params) => {
  const Url = new URL(baseUrl);
  const urlParams = new URLSearchParams(Url.search);
  for (const key in params) {
    if (params[key] !== undefined) {
      urlParams.set(key, params[key]);
    }
  }
  Url.search = urlParams.toString();
  return Url.toString();
};

console.info('expected: https://example.com/?foo=bar');
console.log(getUriWithParam("https://example.com", {foo: "bar"}));

console.info('expected: https://example.com/slug?foo=bar#hash');
console.log(getUriWithParam("https://example.com/slug#hash", {foo: "bar"}));

console.info('expected: https://example.com/?bar=baz&foo=bar');
console.log(getUriWithParam("https://example.com?bar=baz", {foo: "bar"}));

console.info('expected: https://example.com/?foo=baz&bar=baz');
console.log(getUriWithParam("https://example.com?foo=bar&bar=baz", {foo: "baz"}));

Typescript


const getUriWithParam = (
  baseUrl: string,
  params: Record<string, any>
): string => {
  const Url = new URL(baseUrl);
  const urlParams: URLSearchParams = new URLSearchParams(Url.search);
  for (const key in params) {
    if (params[key] !== undefined) {
      urlParams.set(key, params[key]);
    }
  }
  Url.search = urlParams.toString();
  return Url.toString();
};

For React Native

URL is not implemented in React Native. So you have to install react-native-url-polyfill beforehand.

For object params

See the second solution in this answer

2 Comments

This should be the best choice
IE is not supported
20

Here is my library to do that: https://github.com/Mikhus/jsurl

var u = new Url;
u.query.param='value'; // adds or replaces the param
alert(u)

Comments

15

If it's not set or want to update with a new value you can use:

window.location.search = 'param=value'; // or param=new_value

This is in simple Javascript, by the way.

EDIT

You may want to try using the jquery query-object plugin

window.location.search = jQuery.query.set("param", 5);

3 Comments

this wont maintain any other query string parameters on the url though.
you are right, I apologize.. as an update, I added another option to my answer :)
This is not working, because it doesn't reset a value. "add or update"
14

I realize this question is old and has been answered to death, but here's my stab at it. I'm trying to reinvent the wheel here because I was using the currently accepted answer and the mishandling of URL fragments recently bit me in a project.

The function is below. It's quite long, but it was made to be as resilient as possible. I would love suggestions for shortening/improving it. I put together a small jsFiddle test suite for it (or other similar functions). If a function can pass every one of the tests there, I say it's probably good to go.

Update: I came across a cool function for using the DOM to parse URLs, so I incorporated that technique here. It makes the function shorter and more reliable. Props to the author of that function.

/**
 * Add or update a query string parameter. If no URI is given, we use the current
 * window.location.href value for the URI.
 * 
 * Based on the DOM URL parser described here:
 * http://james.padolsey.com/javascript/parsing-urls-with-the-dom/
 *
 * @param   (string)    uri     Optional: The URI to add or update a parameter in
 * @param   (string)    key     The key to add or update
 * @param   (string)    value   The new value to set for key
 *
 * Tested on Chrome 34, Firefox 29, IE 7 and 11
 */
function update_query_string( uri, key, value ) {

    // Use window URL if no query string is provided
    if ( ! uri ) { uri = window.location.href; }

    // Create a dummy element to parse the URI with
    var a = document.createElement( 'a' ), 

        // match the key, optional square brackets, an equals sign or end of string, the optional value
        reg_ex = new RegExp( key + '((?:\\[[^\\]]*\\])?)(=|$)(.*)' ),

        // Setup some additional variables
        qs,
        qs_len,
        key_found = false;

    // Use the JS API to parse the URI 
    a.href = uri;

    // If the URI doesn't have a query string, add it and return
    if ( ! a.search ) {

        a.search = '?' + key + '=' + value;

        return a.href;
    }

    // Split the query string by ampersands
    qs = a.search.replace( /^\?/, '' ).split( /&(?:amp;)?/ );
    qs_len = qs.length; 

    // Loop through each query string part
    while ( qs_len > 0 ) {

        qs_len--;

        // Remove empty elements to prevent double ampersands
        if ( ! qs[qs_len] ) { qs.splice(qs_len, 1); continue; }

        // Check if the current part matches our key
        if ( reg_ex.test( qs[qs_len] ) ) {

            // Replace the current value
            qs[qs_len] = qs[qs_len].replace( reg_ex, key + '$1' ) + '=' + value;

            key_found = true;
        }
    }   

    // If we haven't replaced any occurrences above, add the new parameter and value
    if ( ! key_found ) { qs.push( key + '=' + value ); }

    // Set the new query string
    a.search = '?' + qs.join( '&' );

    return a.href;
}

8 Comments

This looks really good, solid test cases + using the DOM as URL parser. I did find two cases though: example.com/?param=val& => example.com/?param=val&&new=key --double & and example.com/team => example.com/team?new=key expected: team/?new=key some redirect /team?new=key to /team/ and the queries are lost.
Thanks for the failing test case. I updated the fiddle. That first one is tough. Any ideas on how to fix the function for it? The second should be handled no problem and is already covered in the test suite. Maybe I don't understand you though. Feel free to fork the test fiddle to demonstrate what you're seeing.
I added some test cases i ran into and workarounds. I tried to use the DOM as much as possible. Primarily i needed this to also work for relative links within the same domain. jsfiddle.net/Timar/7sjrhbm3
@braed I like the approach because it leaves the heavy lifting to the browser. As you see from a lot of answers here, this problem is not as simple as it seems. There are A LOT of corner cases that a solution needs to cover. Most of them are covered for free when you leverage the DOM.
@braed sure just take a look at the test suite I linked in the answer. A lot of the solutions here that don't rely on the DOM fail it because they don't account for all of the edge cases listed. As for reading, it might be instructive to look at the URL module for node.js. It's not directly related, but it gives you an idea of some of the complexity involved in URL strings.
|
11

window.location.search is read/write.

However - modifying the query string will redirect the page you're on and cause a refresh from the server.

If what you're attempting to do is maintain client side state (and potentially make it bookmark-able), you'll want to modify the URL hash instead of the query string, which keeps you on the same page (window.location.hash is read/write). This is how web sites like twitter.com do this.

You'll also want the back button to work, you'll have to bind javascript events to the hash change event, a good plugin for that is http://benalman.com/projects/jquery-hashchange-plugin/

3 Comments

Twitter no longer modifies hash! Hash is dead, welcome the History API!
it's far from dead. i think you are living in a magical dreamland where legacy browser compatibility is of no concern. this may be the case for you, but it's certainly not the case for the rest of us (or in fact the majority of us). perhaps dying is more appropriate...
One year later, It looks like the only semi-recent browser that does not support it is IE 9
9

Here's my approach: The location.params() function (shown below) can be used as a getter or setter. Examples:

Given the URL is http://example.com/?foo=bar&baz#some-hash,

  1. location.params() will return an object with all the query parameters: {foo: 'bar', baz: true}.
  2. location.params('foo') will return 'bar'.
  3. location.params({foo: undefined, hello: 'world', test: true}) will change the URL to http://example.com/?baz&hello=world&test#some-hash.

Here is the params() function, which can optionally be assigned to the window.location object.

location.params = function(params) {
  var obj = {}, i, parts, len, key, value;

  if (typeof params === 'string') {
    value = location.search.match(new RegExp('[?&]' + params + '=?([^&]*)[&#$]?'));
    return value ? value[1] : undefined;
  }

  var _params = location.search.substr(1).split('&');

  for (i = 0, len = _params.length; i < len; i++) {
    parts = _params[i].split('=');
    if (! parts[0]) {continue;}
    obj[parts[0]] = parts[1] || true;
  }

  if (typeof params !== 'object') {return obj;}

  for (key in params) {
    value = params[key];
    if (typeof value === 'undefined') {
      delete obj[key];
    } else {
      obj[key] = value;
    }
  }

  parts = [];
  for (key in obj) {
    parts.push(key + (obj[key] === true ? '' : '=' + obj[key]));
  }

  location.search = parts.join('&');
};

1 Comment

It's bad practice to mutate things you didn't make in ways they aren't meant to be mutated. What if, for example, a params field is added to the built-in Location class? Then this code would conflict with that. Or perhaps widespread use of this code would prevent such a field from ever being added, as was the case with contains on strings and arrays--they had to name it includes instead due to widespread overwriting of contains.
7

It's so simple with URLSearchParams, supported in all modern browsers (caniuse).

let p = new URLSearchParams();
p.set("foo", "bar");
p.set("name", "Jack & Jill?");
console.log("http://example.com/?" + p.toString());

If you want to modify the existing URL, construct the object like this: new URLSearchParams(window.location.search) and assign the string to window.location.search.

Comments

6

I know this is quite old but i want to fires my working version in here.

function addOrUpdateUrlParam(uri, paramKey, paramVal) {
  var re = new RegExp("([?&])" + paramKey + "=[^&#]*", "i");
  if (re.test(uri)) {
    uri = uri.replace(re, '$1' + paramKey + "=" + paramVal);
  } else {
    var separator = /\?/.test(uri) ? "&" : "?";
    uri = uri + separator + paramKey + "=" + paramVal;
  }
  return uri;
}

jQuery(document).ready(function($) {
  $('#paramKey,#paramValue').on('change', function() {
    if ($('#paramKey').val() != "" && $('#paramValue').val() != "") {
      $('#uri').val(addOrUpdateUrlParam($('#uri').val(), $('#paramKey').val(), $('#paramValue').val()));
    }
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input style="width:100%" type="text" id="uri" value="http://www.example.com/text.php">
<label style="display:block;">paramKey
  <input type="text" id="paramKey">
</label>
<label style="display:block;">paramValue
  <input type="text" id="paramValue">
</label>

NOTE This is a modified version of @elreimundo

3

My take from here (compatible with "use strict"; does not really use jQuery):

function decodeURIParams(query) {
  if (query == null)
    query = window.location.search;
  if (query[0] == '?')
    query = query.substring(1);

  var params = query.split('&');
  var result = {};
  for (var i = 0; i < params.length; i++) {
    var param = params[i];
    var pos = param.indexOf('=');
    if (pos >= 0) {
        var key = decodeURIComponent(param.substring(0, pos));
        var val = decodeURIComponent(param.substring(pos + 1));
        result[key] = val;
    } else {
        var key = decodeURIComponent(param);
        result[key] = true;
    }
  }
  return result;
}

function encodeURIParams(params, addQuestionMark) {
  var pairs = [];
  for (var key in params) if (params.hasOwnProperty(key)) {
    var value = params[key];
    if (value != null) /* matches null and undefined */ {
      pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(value))
    }
  }
  if (pairs.length == 0)
    return '';
  return (addQuestionMark ? '?' : '') + pairs.join('&');
}

//// alternative to $.extend if not using jQuery:
// function mergeObjects(destination, source) {
//   for (var key in source) if (source.hasOwnProperty(key)) {
//     destination[key] = source[key];
//   }
//   return destination;
// }

function navigateWithURIParams(newParams) {
  window.location.search = encodeURIParams($.extend(decodeURIParams(), newParams), true);
}

Example usage:

// add/update parameters
navigateWithURIParams({ foo: 'bar', boz: 42 });

// remove parameter
navigateWithURIParams({ foo: null });

// submit the given form by adding/replacing URI parameters (with jQuery)
$('.filter-form').submit(function(e) {
  e.preventDefault();
  navigateWithURIParams(decodeURIParams($(this).serialize()));
});

Comments

2

Based on the answer @ellemayo gave, I came up with the following solution that allows for disabling of the hash tag if desired:

function updateQueryString(key, value, options) {
    if (!options) options = {};

    var url = options.url || location.href;
    var re = new RegExp("([?&])" + key + "=.*?(&|#|$)(.*)", "gi"), hash;

    hash = url.split('#');
    url = hash[0];
    if (re.test(url)) {
        if (typeof value !== 'undefined' && value !== null) {
            url = url.replace(re, '$1' + key + "=" + value + '$2$3');
        } else {
            url = url.replace(re, '$1$3').replace(/(&|\?)$/, '');
        }
    } else if (typeof value !== 'undefined' && value !== null) {
        var separator = url.indexOf('?') !== -1 ? '&' : '?';
        url = url + separator + key + '=' + value;
    }

    if ((typeof options.hash === 'undefined' || options.hash) &&
        typeof hash[1] !== 'undefined' && hash[1] !== null)
        url += '#' + hash[1];
    return url;
}

Call it like this:

updateQueryString('foo', 'bar', {
    url: 'http://my.example.com#hash',
    hash: false
});

Results in:

http://my.example.com?foo=bar

1 Comment

Stylistic quibble: typeof value !== 'undefined' && value !== null is more explicit, but value != null means the same thing and is more concise.
2

Here is a shorter version that takes care of

  • query with or without a given parameter
  • query with multiple parameter values
  • query containing hash

Code:

var setQueryParameter = function(uri, key, value) {
  var re = new RegExp("([?&])("+ key + "=)[^&#]*", "g");
  if (uri.match(re)) 
    return uri.replace(re, '$1$2' + value);

  // need to add parameter to URI
  var paramString = (uri.indexOf('?') < 0 ? "?" : "&") + key + "=" + value;
  var hashIndex = uri.indexOf('#');
  if (hashIndex < 0)
    return uri + paramString;
  else
    return uri.substring(0, hashIndex) + paramString + uri.substring(hashIndex);
}

The regex description can be found here.

NOTE: This solution is based on @amateur answer, but with many improvements.

Comments

2

Code that appends a list of parameters to an existing url using ES6 and jQuery:

class UrlBuilder {
    static appendParametersToUrl(baseUrl, listOfParams) {

        if (jQuery.isEmptyObject(listOfParams)) {
            return baseUrl;
        }

        const newParams = jQuery.param(listOfParams);

        let partsWithHash = baseUrl.split('#');
        let partsWithParams = partsWithHash[0].split('?');

        let previousParams = '?' + ((partsWithParams.length === 2) ? partsWithParams[1] + '&' : '');
        let previousHash = (partsWithHash.length === 2) ? '#' + partsWithHash[1] : '';

        return partsWithParams[0] + previousParams + newParams + previousHash;
    }
}

Where listOfParams is like

const listOfParams = {
    'name_1': 'value_1',
    'name_2': 'value_2',
    'name_N': 'value_N',
};

Example of Usage:

    UrlBuilder.appendParametersToUrl(urlBase, listOfParams);

Fast tests:

    url = 'http://hello.world';
    console.log('=> ', UrlParameters.appendParametersToUrl(url, null));
    // Output:  http://hello.world

    url = 'http://hello.world#h1';
    console.log('=> ', UrlParameters.appendParametersToUrl(url, null));
    // Output:  http://hello.world#h1

    url = 'http://hello.world';
    params = {'p1': 'v1', 'p2': 'v2'};
    console.log('=> ', UrlParameters.appendParametersToUrl(url, params));
    // Output: http://hello.world?p1=v1&p2=v2

    url = 'http://hello.world?p0=v0';
    params = {'p1': 'v1', 'p2': 'v2'};
    console.log('=> ', UrlParameters.appendParametersToUrl(url, params));
    // Output: http://hello.world?p0=v0&p1=v1&p2=v2

    url = 'http://hello.world#h1';
    params = {'p1': 'v1', 'p2': 'v2'};
    console.log('=> ', UrlParameters.appendParametersToUrl(url, params));
   // Output: http://hello.world?p1=v1&p2=v2#h1

    url = 'http://hello.world?p0=v0#h1';
    params = {'p1': 'v1', 'p2': 'v2'};
    console.log('=> ', UrlParameters.appendParametersToUrl(url, params));
    // Output: http://hello.world?p0=v0&p1=v1&p2=v2#h1

Comments

2

This answer is just a small tweak of ellemayo's answer. It will automatically update the URL instead of just returning the updated string.

function _updateQueryString(key, value, url) {
    if (!url) url = window.location.href;

    let updated = ''
    var re = new RegExp("([?&])" + key + "=.*?(&|#|$)(.*)", "gi"),
        hash;

    if (re.test(url)) {
        if (typeof value !== 'undefined' && value !== null) {
            updated = url.replace(re, '$1' + key + "=" + value + '$2$3');
        } 
        else {
            hash = url.split('#');
            url = hash[0].replace(re, '$1$3').replace(/(&|\?)$/, '');
            if (typeof hash[1] !== 'undefined' && hash[1] !== null) {
                url += '#' + hash[1];
            }
            updated = url;
        }
    }
    else {
        if (typeof value !== 'undefined' && value !== null) {
            var separator = url.indexOf('?') !== -1 ? '&' : '?';
            hash = url.split('#');
            url = hash[0] + separator + key + '=' + value;
            if (typeof hash[1] !== 'undefined' && hash[1] !== null) {
                url += '#' + hash[1];
            }
            updated = url;
        }
        else {
            updated = url;
        }
    }

    window.history.replaceState({ path: updated }, '', updated);
}

Comments

1

To give an code example for modifying window.location.search as suggested by Gal and tradyblix:

var qs = window.location.search || "?";
var param = key + "=" + value; // remember to URI encode your parameters
if (qs.length > 1) {
    // more than just the question mark, so append with ampersand
    qs = qs + "&";
}
qs = qs + param;
window.location.search = qs;

Comments

1

A different approach without using regular expressions. Supports 'hash' anchors at the end of the url as well as multiple question mark charcters (?). Should be slightly faster than the regular expression approach.

function setUrlParameter(url, key, value) {
  var parts = url.split("#", 2), anchor = parts.length > 1 ? "#" + parts[1] : '';
  var query = (url = parts[0]).split("?", 2);
  if (query.length === 1) 
    return url + "?" + key + "=" + value + anchor;

  for (var params = query[query.length - 1].split("&"), i = 0; i < params.length; i++)
    if (params[i].toLowerCase().startsWith(key.toLowerCase() + "="))
      return params[i] = key + "=" + value, query[query.length - 1] = params.join("&"), query.join("?") + anchor;

  return url + "&" + key + "=" + value + anchor
}

Comments

1

Use this function to add, remove and modify query string parameter from URL based on jquery

/**
@param String url
@param object param {key: value} query parameter
*/
function modifyURLQuery(url, param){
    var value = {};

    var query = String(url).split('?');

    if (query[1]) {
        var part = query[1].split('&');

        for (i = 0; i < part.length; i++) {
            var data = part[i].split('=');

            if (data[0] && data[1]) {
                value[data[0]] = data[1];
            }
        }
    }

    value = $.extend(value, param);

    // Remove empty value
    for (i in value){
        if(!value[i]){
            delete value[i];
        }
    }

    // Return url with modified parameter
    if(value){
        return query[0] + '?' + $.param(value);
    } else {
        return query[0];
    }
}

Add new and modify existing parameter to url

var new_url = modifyURLQuery("http://google.com?foo=34", {foo: 50, bar: 45});
// Result: http://google.com?foo=50&bar=45

Remove existing

var new_url = modifyURLQuery("http://google.com?foo=50&bar=45", {bar: null});
// Result: http://google.com?foo=50

Comments

1

Here's my slightly different approach to this, written as an excercise

function addOrChangeParameters( url, params )
{
  let splitParams = {};
  let splitPath = (/(.*)[?](.*)/).exec(url);
  if ( splitPath && splitPath[2] )
    splitPath[2].split("&").forEach( k => { let d = k.split("="); splitParams[d[0]] = d[1]; } );
  let newParams = Object.assign( splitParams, params );
  let finalParams = Object.keys(newParams).map( (a) => a+"="+newParams[a] ).join("&");
  return splitPath ? (splitPath[1] + "?" + finalParams) : (url + "?" + finalParams);
}

usage:

const url = "http://testing.com/path?empty&value1=test&id=3";

addOrChangeParameters( url, {value1:1, empty:"empty", new:0} )

"http://testing.com/path?empty=empty&value1=1&id=3&new=0"

1 Comment

this is a simple and awesome
0

Java script code to find a specific query string and replace its value *

('input.letter').click(function () {
                //0- prepare values
                var qsTargeted = 'letter=' + this.value; //"letter=A";
                var windowUrl = '';
                var qskey = qsTargeted.split('=')[0];
                var qsvalue = qsTargeted.split('=')[1];
                //1- get row url
                var originalURL = window.location.href;
                //2- get query string part, and url
                if (originalURL.split('?').length > 1) //qs is exists
                {
                    windowUrl = originalURL.split('?')[0];
                    var qs = originalURL.split('?')[1];
                    //3- get list of query strings
                    var qsArray = qs.split('&');
                    var flag = false;
                    //4- try to find query string key
                    for (var i = 0; i < qsArray.length; i++) {
                        if (qsArray[i].split('=').length > 0) {
                            if (qskey == qsArray[i].split('=')[0]) {
                                //exists key
                                qsArray[i] = qskey + '=' + qsvalue;
                                flag = true;
                                break;
                            }
                        }
                    }
                    if (!flag)//   //5- if exists modify,else add
                    {
                        qsArray.push(qsTargeted);
                    }
                    var finalQs = qsArray.join('&');
                    //6- prepare final url
                    window.location = windowUrl + '?' + finalQs;
                }
                else {
                    //6- prepare final url
                    //add query string
                    window.location = originalURL + '?' + qsTargeted;
                }
            })
        });

Comments

0

Here's an alternative method using the inbuilt properties of the anchor HTML element:

  • Handles multi-valued parameters.
  • No risk of modifying the # fragment, or anything other than the query string itself.
  • May be a little easier to read? But it is longer.

    var a = document.createElement('a'),

	getHrefWithUpdatedQueryString = function(param, value) {
	    return updatedQueryString(window.location.href, param, value);
	},

	updatedQueryString = function(url, param, value) {
	    /*
	     A function which modifies the query string 
             by setting one parameter to a single value.

	     Any other instances of parameter will be removed/replaced.
	     */
	    var fragment = encodeURIComponent(param) + 
                           '=' + encodeURIComponent(value);

	    a.href = url;

	    if (a.search.length === 0) {
		a.search = '?' + fragment;
	    } else {
		var didReplace = false,
		    // Remove leading '?'
		    parts = a.search.substring(1)
		// Break into pieces
			.split('&'),

		    reassemble = [],
		    len = parts.length;

		for (var i = 0; i < len; i++) {
		    
		    var pieces = parts[i].split('=');
		    if (pieces[0] === param) {
			if (!didReplace) {
			    reassemble.push('&' + fragment);
			    didReplace = true;
			}
		    } else {
			reassemble.push(parts[i]);
		    }
		}

		if (!didReplace) {
		    reassemble.push('&' + fragment);
		}

		a.search = reassemble.join('&');
	    }

	    return a.href;
	};

Comments

0

if you want to set multiple parameters at once:

function updateQueryStringParameters(uri, params) {
    for(key in params){
      var value = params[key],
          re = new RegExp("([?&])" + key + "=.*?(&|$)", "i"),
          separator = uri.indexOf('?') !== -1 ? "&" : "?";
      if (uri.match(re)) {
        uri = uri.replace(re, '$1' + key + "=" + value + '$2');
      }
      else {
        uri = uri + separator + key + "=" + value;
      }
    }
    return uri;
}

same function as @amateur's

if jslint gives you an error add this after the for loop

if(params.hasOwnProperty(key))

1 Comment

Doesn't handle hashes, or parameters not assigned a value(http://abc.def/?a&b&c).
0

There are a lot of awkward and unnecessarily complicated answers on this page. The highest rated one, @amateur's, is quite good, although it has a bit of unnecessary fluff in the RegExp. Here is a slightly more optimal solution with cleaner RegExp and a cleaner replace call:

function updateQueryStringParamsNoHash(uri, key, value) {
  var re = new RegExp("([?&])" + key + "=[^&]*", "i");
  return re.test(uri)
       ? uri.replace(re, '$1' + key + "=" + value)
       : uri + separator + key + "=" + value
  ;
}

As an added bonus, if uri is not a string, you won't get errors for trying to call match or replace on something that may not implement those methods.

And if you want to handle the case of a hash (and you've already done a check for properly formatted HTML), you can leverage the existing function instead of writing a new function containing the same logic:

function updateQueryStringParams(url, key, value) {
    var splitURL = url.split('#');
    var hash = splitURL[1];
    var uri = updateQueryStringParamsNoHash(splitURL[0]);
    return hash == null ? uri : uri + '#' + hash;
}

Or you can make some slight changes to @Adam's otherwise excellent answer:

function updateQueryStringParameter(uri, key, value) {
  var re = new RegExp("([?&])" + key + "=[^&#]*", "i");
  if (re.test(uri)) {
    return uri.replace(re, '$1' + key + "=" + value);
  } else {
    var matchData = uri.match(/^([^#]*)(#.*)?$/);
    var separator = /\?/.test(uri) ? "&" : "?";    
    return matchData[0] + separator + key + "=" + value + (matchData[1] || '');
  }
}

2 Comments

This is a missing bracket in the last function: var matchData = uri.match(/^([^#]*)(#.*)?$/
separator is not defined in updateQueryStringParamsNoHash. In updateQueryStringParameter, everything breaks down if the parameter you're replacing is not assigned a value (e.g. http://abc.def/?a&b&c).
0

This should serve the purpose:

function updateQueryString(url, key, value) {
    var arr =  url.split("#");
    var url = arr[0];
    var fragmentId = arr[1];
    var updatedQS = "";
    if (url.indexOf("?") == -1) {
        updatedQS = encodeURIComponent(key) + "=" + encodeURIComponent(value);
    }
    else {
        updatedQS = addOrModifyQS(url.substring(url.indexOf("?") + 1), key, value); 
    }
    url = url.substring(0, url.indexOf("?")) + "?" + updatedQS;
    if (typeof fragmentId !== 'undefined') {
        url = url + "#" + fragmentId;
    }
    return url;
}

function addOrModifyQS(queryStrings, key, value) {
    var oldQueryStrings = queryStrings.split("&");
    var newQueryStrings = new Array();
    var isNewKey = true;
    for (var i in oldQueryStrings) {
        var currItem = oldQueryStrings[i];
        var searchKey = key + "=";
        if (currItem.indexOf(searchKey) != -1) {
            currItem = encodeURIComponent(key) + "=" + encodeURIComponent(value);
            isNewKey = false;
        }
        newQueryStrings.push(currItem);
    }
    if (isNewKey) {
        newQueryStrings.push(encodeURIComponent(key) + "=" + encodeURIComponent(value));
    }
    return newQueryStrings.join("&");
}   

Comments

0

By using jQuery we can do like below

var query_object = $.query_string;
query_object["KEY"] = "VALUE";
var new_url = window.location.pathname + '?'+$.param(query_object)

In variable new_url we will have new query parameters.

Reference: http://api.jquery.com/jquery.param/

Comments

0

I wanted something that:

  • Uses the browser's native URL API
  • Can add, update, get, or delete
  • Expects the query string after the hash e.g. for single page applications

function queryParam(options = {}) {

  var defaults = {
    method: 'set',
    url: window.location.href,
    key: undefined,
    value: undefined,
  }

  for (var prop in defaults) {
    options[prop] = typeof options[prop] !== 'undefined' ? options[prop] : defaults[prop]
  }

  const existing = (options.url.lastIndexOf('?') > options.url.lastIndexOf('#')) ? options.url.substr(options.url.lastIndexOf('?') + 1) : ''

  const query = new URLSearchParams(existing)

  if (options.method === 'set') {
    query.set(options.key, options.value)

    return `${options.url.replace(`?${existing}`, '')}?${query.toString()}`
  } else if (options.method === 'get') {
    const val = query.get(options.key)
    let result = val === null ? val : val.toString()

    return result
  } else if (options.method === 'delete') {
    query.delete(options.key)

    let result = `${options.url.replace(`?${existing}`, '')}?${query.toString()}`
    const lastChar = result.charAt(result.length - 1)

    if (lastChar === '?') {
      result = `${options.url.replace(`?${existing}`, '')}`
    }

    return result
  }
}

// Usage:
let url = 'https://example.com/sandbox/#page/'

url = queryParam({
  url,
  method: 'set',
  key: 'my-first-param',
  value: 'me'
})
console.log(url)

url = queryParam({
  url,
  method: 'set',
  key: 'my-second-param',
  value: 'you'
})
console.log(url)

url = queryParam({
  url,
  method: 'set',
  key: 'my-second-param',
  value: 'whomever'
})
console.log(url)

url = queryParam({
  url,
  method: 'delete',
  key: 'my-first-param'
})
console.log(url)

const mySecondParam = queryParam({
  url,
  method: 'get',
  key: 'my-second-param',
})
console.log(mySecondParam)

url = queryParam({
  url,
  method: 'delete',
  key: 'my-second-param'
})
console.log(url)

Comments

0
function updateQueryStringParam(key, value) {
  let url = new URL(window.location.href);
  url.searchParams.set(key, value); // Add or update the parameter
  window.history.replaceState({}, '', url);
}

updateQueryStringParam('page', '2');

It works well in most cases:

  • Adds the parameter if missing.

  • Updates the parameter if present.

  • Retains other query parameters.

  • Retains URL hash (#fragment) automatically.

  • Doesn’t reload the page.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.