10

How can you set URL parameters using History.pushState() to avoid browser refreshes? If there is a not a simple JS solution, is there already a popular library or built in function for jQuery?

Here is a relevant SO question, where the accepted answer does not actually work according to comments & my test (it removes the query string instead of updating a value): history.pushState() change query values

Just to be clear, I am referring to the URL parameters in a query string: http://google.com/page?name=don so we could change don to tim without causing a reload.

Here is one possible solution I found. However I'm nervous about using a JS library that only has 2 followers :P

asked Mar 7, 2014 at 19:16
4
  • The idea behind the state object (the first parameter for pushState()) is to set data that is accessible without having to bother with query string parameters. Is there a reason you don't want to use that? Commented Mar 7, 2014 at 19:20
  • @AndyE - I'm not sure I follow. If I do history.pushState({name: "don"}, "some page title", "/page") to set the state, and then use window.location.search to see the URL params, it is empty. Are you saying I am able access the value for name? Commented Mar 7, 2014 at 19:33
  • 1
    Changing the url forces refreshes in most browsers. If you can put your variable after a # then you'll stop the refresh, as the browser will interpret that as a different location on the same page. Commented Mar 7, 2014 at 19:51
  • @problemPotato - I'm aware of hash fragments, that's not the question I'm asking about. Changing the URL does not force a refresh in "most browsers" either, please see docs for the js history API we are discussing here. Commented Mar 7, 2014 at 20:11

3 Answers 3

14

You can just use queryString.push('my_param_key', 'some_new_value') from the small library below.

It will update your URL param using history.push, so the browser will not refresh.

It will only affect the param you wish to change, it will leave the path and other params unaffected.

/*!
 query-string
 Parse and stringify URL query strings
 https://github.com/sindresorhus/query-string
 by Sindre Sorhus
 MIT License
*/
(function () {
 'use strict';
 var queryString = {};
 queryString.parse = function (str) {
 if (typeof str !== 'string') {
 return {};
 }
 str = str.trim().replace(/^\?/, '');
 if (!str) {
 return {};
 }
 return str.trim().split('&').reduce(function (ret, param) {
 var parts = param.replace(/\+/g, ' ').split('=');
 var key = parts[0];
 var val = parts[1];
 key = decodeURIComponent(key);
 // missing `=` should be `null`:
 // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters
 val = val === undefined ? null : decodeURIComponent(val);
 if (!ret.hasOwnProperty(key)) {
 ret[key] = val;
 } else if (Array.isArray(ret[key])) {
 ret[key].push(val);
 } else {
 ret[key] = [ret[key], val];
 }
 return ret;
 }, {});
 };
 queryString.stringify = function (obj) {
 return obj ? Object.keys(obj).map(function (key) {
 var val = obj[key];
 if (Array.isArray(val)) {
 return val.map(function (val2) {
 return encodeURIComponent(key) + '=' + encodeURIComponent(val2);
 }).join('&');
 }
 return encodeURIComponent(key) + '=' + encodeURIComponent(val);
 }).join('&') : '';
 };
 queryString.push = function (key, new_value) {
 var params = queryString.parse(location.search);
 params[key] = new_value;
 var new_params_string = queryString.stringify(params)
 history.pushState({}, "", window.location.pathname + '?' + new_params_string);
 }
 if (typeof module !== 'undefined' && module.exports) {
 module.exports = queryString;
 } else {
 window.queryString = queryString;
 }
})();
answered Mar 8, 2014 at 6:02
Sign up to request clarification or add additional context in comments.

1 Comment

Just a note for anyone who went to github first, queryString.push was added to the library in this answer
1

Answering to the question in your comment, you'd be able to read those properties from history.state, a property that holds the value of the stat for the current URL. Whenever you go back and forward you'll receive a popstate event and you will be able tor read the state you pushed, which is far easier than dealing with urls.

Of course, when you go back or forward to a new entry in the history list pushed with pushState() or replaceState() the page does not reload.

You can read more about the History object in the MDN.

answered Mar 7, 2014 at 19:50

2 Comments

Thanks @Oscar, but when you use history.state - it prevents you from sharing URL's - something I would like to support for this case.
You're right, it is not a good solution if you want to share the urls. Try then the document.location.replace() method, adding a hash to the url (the part after a '#'). Then, on page load, you can get the parameters (or whatever you had put there, it's just a string), via document.location.hash.
1

Here is a simple function I wrote it isn't as neat as the above answer but it does the trick...

 function changeUrlParam (param, value) {
 var currentURL = window.location.href;
 var urlObject = currentURL.split('?');
 var newQueryString = '?';
 value = encodeURIComponent(value);
 if(urlObject.length > 1){
 var queries = urlObject[1].split('&');
 var updatedExistingParam = false;
 for (i = 0; i < queries.length; i++){
 var queryItem = queries[i].split('=');
 if(queryItem.length > 1){
 if(queryItem[0] == param){
 newQueryString += queryItem[0] + '=' + value + '&';
 updatedExistingParam = true;
 }else{
 newQueryString += queryItem[0] + '=' + queryItem[1] + '&';
 }
 }
 }
 if(!updatedExistingParam){
 newQueryString += param + '=' + value + '&';
 }
 }else{
 newQueryString += param + '=' + value + '&';
 }
 window.history.replaceState('', '', urlObject[0] + newQueryString.slice(0, -1));
 }
answered Sep 9, 2016 at 21:56

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.