Persistir variables entre cargas de página
Estoy tratando de capturar el botón de enviar de mi formulario y, si se envía el formulario, la página se actualiza y muestro algunos campos ocultos. Me gustaría saber si el formulario se envió antes o no y, si se envió al recargar, me gustaría mostrar los campos ocultos. Estaba intentando utilizar una variable global para lograr esto, sin embargo, no pude hacer que funcionara correctamente.
Esto es lo que probé:
var clicked = false;
$(document).ready(function() {
$("input[type='submit'][value='Search']").attr("onclick", "form.act.value='detailSearch'; clicked = true; return true;");
if (clicked == true) {
// show hidden fields
} else {
// don't show hidden fields
}
});
¿Alguna sugerencia sobre lo que está mal con este código?
Como HTTP no tiene estado, cada vez que cargue la página, utilizará los valores iniciales de lo que haya configurado en JavaScript. No puede establecer una variable global en JS y simplemente hacer que ese valor permanezca después de cargar la página nuevamente.
Hay un par de formas de almacenar el valor en otro lugar para poder inicializarlo al cargarlo usando JavaScript.
cadena de consulta
Al enviar un formulario utilizando el GET
método, la URL se actualiza con una cadena de consulta ( ?parameter=value&something=42
). Puede utilizar esto configurando un campo de entrada en el formulario con un valor determinado. Este sería el ejemplo más sencillo:
<form method="GET">
<input type="hidden" name="clicked" value="true" />
<input type="submit" />
</form>
En la carga inicial de la página, no se establece ninguna cadena de consulta. Cuando envía este formulario, la combinación name
y value
de la entrada se pasan en la cadena de consulta como clicked=true
. Entonces, cuando la página se cargue nuevamente con esa cadena de consulta, podrá verificar si se hizo clic en el botón.
Para leer estos datos, puede utilizar el siguiente script al cargar la página:
function getParameterByName(name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(location.search);
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
var clicked = getParameterByName('clicked');
( Fuente )
La capacidad de usar esto depende de cómo funciona actualmente su formulario; si ya usa un POST, esto podría ser problemático.
Además, para conjuntos de datos más grandes esto no es óptimo. Pasar una cadena no es gran cosa, pero para matrices y objetos de datos probablemente deberías usar almacenamiento web o cookies. Si bien los detalles difieren un poco entre los navegadores, el límite práctico para la longitud del URI es de alrededor de 2000 caracteres.
Almacenamiento web
Con la introducción de HTML5 también obtuvimos el almacenamiento web, que le permite guardar información en el navegador al cargar la página. Hay una localStorage
que puede guardar datos durante un período más largo (siempre que el usuario no los borre manualmente) y sessionStorage
otra que guarda datos solo durante su sesión de navegación actual. Esto último es útil para usted aquí, porque no desea mantener "clic" establecido en verdadero cuando el usuario regrese más tarde.
Aquí configuro el almacenamiento en el evento de clic del botón, pero también puedes vincularlo al envío del formulario o cualquier otra cosa.
$('input[type="submit"][value="Search"]').click(function() {
sessionStorage.setItem('clicked', 'true');
});
Luego, cuando cargas la página, puedes verificar si está configurada usando esto:
var clicked = sessionStorage.getItem('clicked');
Aunque este valor sólo se guarda durante esta sesión de navegación, es posible que desee restablecerlo antes. Para hacerlo, use:
sessionStorage.removeItem('clicked');
Si desea guardar un objeto o matriz JS, debe convertirlo en una cadena. Según la especificación, debería ser posible guardar otros tipos de datos, pero esto aún no está implementado correctamente en todos los navegadores.
//set
localStorage.setItem('myObject', JSON.stringify(myObject));
//get
var myObject = JSON.parse(localStorage.getItem('myObject'));
La compatibilidad con el navegador es bastante buena , por lo que deberías estar seguro de usarla a menos que necesites admitir navegadores muy antiguos/oscuros. El almacenamiento web es el futuro.
Galletas
Una alternativa al almacenamiento web es guardar los datos en una cookie. Las cookies se crean principalmente para leer datos del lado del servidor, pero también se pueden utilizar para datos puramente del lado del cliente.
Ya utilizas jQuery, lo que facilita bastante la configuración de cookies. Nuevamente, uso el click
evento aquí pero podría usarse en cualquier lugar.
$('input[type="submit"][value="Search"]').click(function() {
$.cookie('clicked', 'true', {expires: 1}); // expires in 1 day
});
Luego, al cargar la página, puede leer la cookie de esta manera:
var clicked = $.cookie('clicked');
Como las cookies persisten en todas las sesiones, en su caso, deberá desactivarlas tan pronto como haya hecho lo que sea necesario con ellas. No querrás que el usuario regrese un día después y aún así esté clicked
configurado como verdadero.
if(clicked === "true") {
//doYourStuff();
$.cookie('clicked', null);
}
( Aquí se puede encontrar una forma no basada en jQuery de configurar/leer cookies )
Personalmente, no usaría una cookie para algo tan simple como recordar el estado en el que se hizo clic, pero si la cadena de consulta no es una opción y necesita admitir navegadores muy antiguos que no admiten sessionStorage, esto funcionará. Primero debe implementar eso verificando el almacenamiento de sesión y solo si eso falla, use el método de cookie.
nombre.ventana
Aunque esto me parece un truco que probablemente se originó antes de localStorage/sessionStorage, podrías almacenar información en la window.name
propiedad:
window.name = "my value"
Solo puede almacenar cadenas, por lo que si desea guardar un objeto, deberá codificarlo como en el localStorage
ejemplo anterior:
window.name = JSON.stringify({ clicked: true });
La principal diferencia es que esta información se conserva no solo en las actualizaciones de la página sino también en diferentes dominios. Sin embargo, está restringido a la pestaña actual en la que se encuentra.
Esto significa que puede guardar cierta información en su página y, siempre que el usuario permanezca en esa pestaña, puede acceder a esa misma información incluso si navega a otro sitio web y regresa. En general, desaconsejaría el uso de esto a menos que necesite almacenar información entre dominios durante una única sesión de navegación.
Intente utilizar $.holdReady()
,history
function show() {
return $("form input[type=hidden]")
.replaceWith(function(i, el) {
return "<input type=text>"
});
}
$.holdReady(true);
if (history.state !== null && history.state.clicked === true) {
// show hidden fields
// if `history.state.clicked === true` ,
// replace `input type=hidden` with `input type=text`
show();
console.log(history);
} else {
// don't show hidden fields
console.log(history);
}
$.holdReady(false);
$(document).ready(function() {
$("input[type=submit][value=Search]")
.on("click", function(e) {
e.preventDefault();
if (history.state === null) {
// do stuff
history.pushState({"clicked":true});
// replace `input type=hidden` with `input type=text`
show();
console.log(history);
} else {
// do other stuff
};
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form method="POST">
<input type="text" name="name" value="" />
<input type="submit" value="Search" />
<input type="hidden" />
<input type="hidden" />
</form>
Usar localeStorage
o sessionStorage
parece ser la mejor opción.
En lugar de guardar la clicked
variable en el alcance global, guárdela de esta manera:
if(localeStorage.getItem("clicked") === null)
localeStorage.setItem("clicked", "FALSE"); // for the first time
$(document).ready(function() {
$("input[type='submit'][value='Search']").attr("onclick", "form.act.value='detailSearch';return true;");
var clicked = localeStorage.getItem("clicked") == "FALSE" ? "TRUE" : "FALSE";
localeStorage.setItem("clicked", clicked);
if (clicked == "TRUE") {
// show hidden fields
} else {
// don't show hidden fields
}
});