Skip to content

Vinculación de Entradas de Formularios

Cuando tratamos con formularios en el frontend, a menudo necesitamos sincronizar el estado de los elementos de entrada del formulario con el estado correspondiente en JavaScript. Puede ser incómodo configurar manualmente los enlaces de valores y cambiar los escuchadores de eventos:

template
<input
  :value="text"
  @input="event => text = event.target.value">

La directiva v-model nos ayuda a simplificar lo anterior a:

template
<input v-model="text">

Además, v-model se puede utilizar en entradas de diferentes tipos, <textarea>, y elementos <select>. Esto se propaga automáticamente a diferentes propiedades del DOM y pares de eventos basados en el elemento en el que se utiliza:

  • <input> con tipos de texto y elementos <textarea> utilizan la propiedad value y el evento input;
  • <input type="checkbox"> al igual que <input type="radio"> utilizan la propiedad checked y el evento change;
  • <select> utiliza la propiedad value y change como un evento.

Nota

v-model ignorará los atributos iniciales value, checked o selected encontrados en cualquier elemento del formulario. Este siempre tratará el estado del JavaScript enlazado actual como la fuente de la verdad. Debes declarar el valor inicial en el lado de JavaScript, utilizando la opción datalas APIs de reactividad.

Uso Básico

Texto

template
<p>El mensaje es: {{ message }}</p>
<input v-model="message" placeholder="edítame" />

El mensaje es:

Nota

Para los lenguajes que requieren un IME (Chino, Japonés, Coreano, etc.), notarás que el v-model no se actualiza durante la composición del IME. Si quieres responder también a estas actualizaciones, utiliza un receptor de eventos input y un enlace value en lugar de utilizar v-model.

Texto Multilínea

template
<span>El mensaje multilínea es:</span>
<p style="white-space: pre-line;">{{ message }}</p>
<textarea v-model="message" placeholder="agrega múltiples líneas"></textarea>
El mensaje multilínea es:

Observa que la interpolación dentro del <textarea> no funcionará. En su lugar, utiliza v-model.

template
<!-- erróneo -->
<textarea>{{ text }}</textarea>

<!-- correcto -->
<textarea v-model="text"></textarea>

Checkbox

Un único checkbox, con valor booleano:

template
<input type="checkbox" id="checkbox" v-model="checked" />
<label for="checkbox">{{ checked }}</label>

También podemos vincular múltiples checkboxes al mismo array o valor Set:

js
const checkedNames = ref([])
js
export default {
  data() {
    return {
      checkedNames: []
    }
  }
}
template
<div>Nombres verificados: {{ checkedNames }}</div>

<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>

<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>

<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
Nombres verificados: []

En este caso, el array checkedNames siempre contendrá los valores de las casillas seleccionadas en ese momento.

Radio

template
<div>Seleccionado: {{ picked }}</div>

<input type="radio" id="one" value="Uno" v-model="picked" />
<label for="one">Uno</label>

<input type="radio" id="two" value="Dos" v-model="picked" />
<label for="two">Dos</label>
Seleccionado:

Select

Select Simple:

template
<div>Selección: {{ selected }}</div>

<select v-model="selected">
  <option disabled value="">Por favor, selecciona uno</option>
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>
Selección:

Nota

Si el valor inicial de tu expresión v-model no coincide con ninguna de las opciones, el elemento <select> se mostrará en un estado "no seleccionado". En iOS esto hará que el usuario no pueda seleccionar el primer elemento porque iOS no dispara un evento de cambio en este caso. Por lo tanto, se recomienda proporcionar una opción deshabilitada con un valor vacío, como se demuestra en el ejemplo anterior.

Selección múltiple (vinculada a un array):

template
<div>Seleccionado: {{ selected }}</div>

<select v-model="selected" multiple>
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>
Seleccionado: []

Las opciones de selección se pueden representar dinámicamente con v-for:

js
const selected = ref('A')

const options = ref([
  { text: 'Uno', value: 'A' },
  { text: 'Dos', value: 'B' },
  { text: 'Tres', value: 'C' }
])
js
export default {
  data() {
    return {
      selected: 'A',
      options: [
        { text: 'Uno', value: 'A' },
        { text: 'Dos', value: 'B' },
        { text: 'Tres', value: 'C' }
      ]
    }
  }
}
template
<select v-model="selected">
  <option v-for="option in options" :value="option.value">
    {{ option.text }}
  </option>
</select>

<div>Seleccionado: {{ selected }}</div>

Vinculación de Valores

En las opciones radio, checkbox y select, los valores de enlace del v-model suelen ser cadenas estáticas (o booleanas en el caso de los checkbox):

template
<!-- `picked` es una cadena "a" cuando se selecciona -->
<input type="radio" v-model="picked" value="a" />

<!-- `toggle` puede ser verdadero o falso -->
<input type="checkbox" v-model="toggle" />

<!-- `selected` es una cadena "abc" cuando se selecciona la primera opción -->
<select v-model="selected">
  <option value="abc">ABC</option>
</select>

Pero en ocasiones podemos querer vincular el valor a una propiedad dinámica de la instancia activa actual. Para ello podemos utilizar v-bind. Además, el uso de v-bind nos permite vincular el valor de entrada a valores que no son de cadena.

Checkbox

template
<input
  type="checkbox"
  v-model="toggle"
  true-value="sí"
  false-value="no" />

true-value y false-value son atributos específicos de Vue que sólo funcionan con v-model. En este caso, el valor de la propiedad toggle se establecerá en 'sí' cuando la casilla esté marcada, y en 'no' cuando esté desmarcada. También puedes vincularlos a valores dinámicos usando v-bind:

template
<input
  type="checkbox"
  v-model="toggle"
  :true-value="dynamicTrueValue"
  :false-value="dynamicFalseValue" />

Tip

Los atributos true-value y false-value no afectan al atributo value de la entrada, porque los navegadores no incluyen las casillas sin marcar en los envíos de formularios. Para garantizar que uno de los dos valores se envíe en un formulario (por ejemplo, "sí" o "no"), utiliza entradas de radio en su lugar.

Radio

template
<input type="radio" v-model="pick" :value="primero" />
<input type="radio" v-model="pick" :value="segundo" />

pick se establecerá con el valor de primero cuando se marque la primera entrada de radio, y se establecerá con el valor de segundo cuando se marque la segunda.

Opciones de Select

template
<select v-model="selected">
  <!-- objeto literal en línea -->
  <option :value="{ number: 123 }">123</option>
</select>

v-model admite también la vinculación de valores que no sean cadenas. En el ejemplo anterior, cuando se selecciona la opción, selected se establecerá en el valor literal del objeto de { number: 123 }.

Modificadores

.lazy

Por defecto, v-model sincroniza la entrada con los datos después de cada evento input (con la excepción de la composición IME, como se ha indicado anteriormente). Puedes añadir el modificador lazy para sincronizar después de los eventos change:

template
<!-- sincronizado después de "change" en lugar de "input" -->
<input v-model.lazy="msg" />

.number

Si quieres que la entrada del usuario sea automáticamente tipificada como un número, puedes añadir el modificador number a tus entradas gestionadas por v-model:

template
<input v-model.number="age" />

Si el valor no puede ser procesado con parseFloat(), entonces se utiliza el valor original.

El modificador number se aplica automáticamente si la entrada tiene type="number".

.trim

Si quieres que los espacios en blanco de la entrada del usuario se recorten automáticamente, puedes añadir el modificador trim a tus entradas gestionadas por v-model:

template
<input v-model.trim="msg" />

v-model con Componentes

Si aún no estás familiarizado con los componentes de Vue, puedes saltarte esto por ahora.

Los tipos de entrada incorporados en HTML no siempre satisfacen tus necesidades. Afortunadamente, los componentes de Vue te permiten construir entradas reutilizables con un comportamiento completamente personalizado. ¡Estas entradas incluso funcionan con v-model! Para aprender más, lee sobre Uso con v-model en la guía de Componentes.

Vinculación de Entradas de Formularios has loaded