Tengo un formulario con algunas entradas y un CSS adjunto que usa selectores de valor de atributo para cambiar el color de fondo de la entrada según el valor.

Ejemplo

<!DOCTYPE html>
<html>
  <head><style>
    input[value="foo"] { background-color: red; }
  </style></head>
  <body>
    <form>
     <input value="foo" />
     <button/>
    </form>
  </body>
</html>

Si uso foo como valor al cargar, como en el código, el campo estará rojo al cargar, pero si lo cambio, permanecerá rojo. Lo mismo si cambio el valor de la entrada a foo, no cambiará el color de fondo.

Del mismo modo, si uso .val() en jQuery. Aparentemente, un valor "dinámico" se cambia en estos casos, mientras que el CSS se refiere a un valor "estático".

$('button').on('click', function(ev) {
  ev.preventDefault();
  $('input[value="foo"]').val('bar');
  // $('input[value="bar"]').val('baz'); // nothing is found
});

Espero que este código cambie el campo de foo a bar, luego bar a baz, pero en el segundo selector no se encuentra el campo.

Si uso el método attr, las cosas parecen funcionar, pero en la documentación de jQuery (y muchas respuestas aquí en SO), val es el camino a seguir.

¿Por qué es así y por qué debo usar val()?

4
Max O'Connor 1 mar. 2018 a las 18:02

4 respuestas

La mejor respuesta

"¿Por qué es así ...?

Es un selector de atributos, y el atributo no cambia cuando actualiza la propiedad .value, por lo que deberá cambiar explícitamente el atributo.

$('button').on('click', function(ev) {
  ev.preventDefault();
  $('input[value="foo"]').val('bar').attr("value", "bar");
  $('input[value="bar"]').val('baz');
});
input[value="foo"] {
  background-color: red;
}

input[value="bar"] {
  background-color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>

<form>
  <input value="foo" />
  <button/>
</form>

Pero eso no funcionará cuando el usuario cambie el valor a menos que conecte un controlador .on("input"... para mantener el atributo sincronizado con la propiedad.

$("input").on("input", function() {
  this.setAttribute("value", this.value);
});
input[value="foo"] {
  background-color: red;
}

input[value="bar"] {
  background-color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>

<form>
  Change the value to "bar"
  <input value="foo" />
</form>

"... y ¿por qué debo usar val() en absoluto?"

Simplemente para obtener y establecer el valor manteniendo el valor original a través del atributo.

No es tan común necesitar que se sincronicen. La selección DOM por valor es un poco como la selección DOM por contenido de texto. Simplemente no se necesita con tanta frecuencia, y a veces hay una mejor manera de resolver el problema.

4
1 mar. 2018 a las 15:17

Ciertamente estoy equivocado en esto para cualquiera que conozca los tecnicismos de HTML, pero para mi propia intuición, siempre pensé en todo lo que entra en el archivo HTML como un atributo y cualquier valor después de eso como propiedades (supongo que puede llamarlos valores de tiempo de ejecución). Si desea una comprensión más profunda, deberá buscarlo en Google, ya que no tengo ese conocimiento :) Solo tenga en cuenta que mi resumen aquí está terriblemente simplificado.

Puedes hacer el siguiente experimento. En Chrome, si presiona Ctrl + J (lo siento, no sé cuál es el combo para otros navegadores), puede abrir la consola de JavaScript. Ahí entra

$("input[value=foo]").val("bar");

Luego vaya al explorador DOM y observe que el valor atributo no ha cambiado. Para cambiarlo, debe usar la función

$("input[value=foo]").attr("value","bar");

Entonces podrás lograr lo que estás buscando.

0
Kamil Jarosz 1 mar. 2018 a las 15:28
input[value="foo"]

Selecciona elementos input que tienen un atributo explícito value que es igual a foo.

Escribir foo en un elemento input no crea dicho atributo , ni escribir nada más eliminar un atributo en un input que tiene el atributo value="foo".

val() de jQuery es el enfoque correcto para leer el valor, el problema es que su selector $('input[value="bar"]') no puede encontrar nada porque establecer el valor propiedad de input no cambie / agregue el atributo .

1
connexo 1 mar. 2018 a las 15:07

Espero que este fragmento explique bien

$input = $('input')

console.log('val:', $input.val())
console.log('attr:', $input.attr('value'))

// attr will get the attribute from html not the *dynamic* value has been set
$input.val('bar')
console.log('val:', $input.val())
console.log('attr:', $input.attr('value'))

// same here when you use val you change the property value of input not the attribute
$input.attr('value', 'bazzz')

console.log('val:', $input.val())
console.log('attr:', $input.attr('value'))
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input value="foo" />
0
Đào Minh Hạt 1 mar. 2018 a las 15:14