¿Cómo puedo agregar o actualizar un parámetro de cadena de consulta?
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.
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;
}
}
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 foo
se ha configurado bar
independientemente de si ya existía o no.
Sin embargo, la asignación anterior window.location.search
provocará 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.
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
Puede utilizar la API de URL nativa del navegador para hacer esto de una manera muy sencilla, donde key
y value
son 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 url
objeto. 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);
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 === undefined
como forma de indicar eliminación. Podría usar value === false
o 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/