¿Cómo puedo agregar o actualizar un parámetro de cadena de consulta?

Resuelto amateur asked hace 13 años • 30 respuestas

Con javascript, ¿cómo puedo agregar un parámetro de cadena de consulta a la URL si no está presente o, si está presente, actualizar el valor actual? Estoy usando jquery para el desarrollo del lado de mi cliente.

amateur avatar May 14 '11 07:05 amateur
Aceptado

Escribí la siguiente función que logra lo que quiero lograr:

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;
  }
}
amateur avatar May 16 '2011 17:05 amateur

Actualización (2020): URLSearchParams ahora es compatible con todos los navegadores modernos.

La utilidad URLSearchParams puede resultar útil para esto en combinación con window.location.search. Por ejemplo:

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

Ahora foose ha configurado barindependientemente de si ya existía o no.

Sin embargo, la asignación anterior window.location.searchprovocará una carga de la página, por lo que si eso no es deseable, utilice la API Historial de la siguiente manera:

if ('URLSearchParams' in window) {
    var searchParams = new URLSearchParams(window.location.search)
    searchParams.set("foo", "bar");
    var newRelativePathQuery = window.location.pathname + '?' + searchParams.toString();
    history.pushState(null, '', newRelativePathQuery);
}

Ahora no necesita escribir su propia expresión regular o lógica para manejar la posible existencia de cadenas de consulta.

Sin embargo, la compatibilidad con el navegador es deficiente, ya que actualmente es experimental y solo se utiliza en versiones recientes de Chrome, Firefox, Safari, iOS Safari, Android Browser, Android Chrome y Opera. Úselo con un polyfill si decide usarlo.

Anthony Manning-Franklin avatar Jan 09 '2017 06:01 Anthony Manning-Franklin

Amplié la solución y la combiné con otra que encontré para reemplazar/actualizar/eliminar los parámetros de la cadena de consulta según la entrada de los usuarios y teniendo en cuenta el anclaje de las URL.

Si no se proporciona un valor, se eliminará el parámetro; si se proporciona uno, se agregará/actualizará el parámetro. Si no se proporciona ninguna URL, se obtendrá de 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;
        }
    }
}

Actualizar

Hubo un error al eliminar el primer parámetro en la cadena de consulta. Modifiqué la expresión regular y probé para incluir una solución.

Segunda actualización

Según lo sugerido por @JarónBarends: modifique la verificación de valores para compararlos con indefinidos y nulos para permitir establecer valores 0

Tercera actualización

Hubo un error por el cual al eliminar una variable de cadena de consulta directamente antes de un hashtag se perdía el símbolo del hashtag, lo cual se ha solucionado.

Cuarta Actualización

Gracias @rooby por señalar una optimización de expresiones regulares en el primer objeto RegExp. Establezca la expresión regular inicial en ([?&]) debido a un problema con el uso (\?|&) encontrado por @YonatanKarni

Quinta actualización

Eliminación de la declaración de hash var en la declaración if/else

ellemayo avatar Jul 25 '2012 16:07 ellemayo

Puede utilizar la API de URL nativa del navegador para hacer esto de una manera muy sencilla, donde keyy valueson el nombre y el valor del parámetro, respectivamente.

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

Esto preservará todo lo relacionado con la URL y solo cambiará o agregará un parámetro de consulta.

Luego puedes hacer lo que quieras con el urlobjeto. Ejemplos:

// 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);
Grant Gryczan avatar Jul 23 '2021 13:07 Grant Gryczan

Basado en la respuesta de @amateur (y ahora incorporando la solución del comentario de @j_walker_dev), pero teniendo en cuenta el comentario sobre etiquetas hash en la URL, uso lo siguiente:

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;
  }
}

Editado para corregir [?|&]la expresión regular que, por supuesto, debería ser [?&]como se indica en los comentarios.

Editar: versión alternativa para admitir la eliminación de parámetros de URL también. Lo he utilizado value === undefinedcomo forma de indicar eliminación. Podría usar value === falseo incluso un parámetro de entrada separado según se desee.

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;
    }
  }
}

Véalo en acción en https://jsfiddle.net/cdt16wex/

Adam avatar Feb 22 '2013 11:02 Adam