Clique aqui para a documentação da v3.x.

Você está navegando a documentação da v2.x e anterior. Para a v3.x, clique aqui.

Interligações em Formulários

Uso Básico

Você pode usar a diretiva v-model para criar interligações de mão dupla (two-way binding) entre os dados e elementos input, textarea e select de formulários. A diretiva automaticamente busca a maneira correta de atualizar o elemento com base no tipo de entrada. Embora um pouco mágico, v-model é essencialmente açúcar sintático para atualização de dados através de eventos de entrada do usuário, além de cuidados especiais para alguns casos extremos.

A diretiva v-model irá ignorar o estado inicial de value, checked ou selected encontrado em qualquer elemento de formulário. Sempre se tratará a instância Vue como a fonte dos dados verdadeiros. Ou seja, declare os valores iniciais no lado JavaScript, dentro da opção data de seu componente.

v-model usa internamente diferentes propriedades e emite diferentes eventos para diferentes elementos input:

Para linguagens que requerem um IME (Chinês, Japonês, Coreano, etc.), você notará que v-model não é atualizado durante a atualização da composição IME. Se você quiser atender à estas atualizações, use o evento input em vez do v-model.

Input

<input v-model="message" placeholder="Me edite">
<p>A mensagem é: {{ message }}</p>

A mensagem é: {{ message }}

Textarea

<span>Mensagem com múltiplas linhas:</span>
<p style="white-space: pre-line;">{{ message }}</p>
<br>
<textarea v-model="message" placeholder="Escreva bastante"></textarea>
Mensagem com múltiplas linhas:

{{ message }}


Interpolação em textareas (<textarea>{{text}}</textarea>) não funciona. Em vez disso, sempre use v-model.

Checkbox

Checkbox simples com valor booleano:

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

Múltiplos checkboxes, associados a um mesmo Array:

<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>
<br>
<span>Nomes assinalados: {{ checkedNames }}</span>
new Vue({
  el: '...',
  data: {
    checkedNames: []
  }
})

Nomes assinalados: {{ checkedNames }}

Radio

<input type="radio" id="one" value="Um" v-model="picked">
<label for="one">Um</label>
<br>
<input type="radio" id="two" value="Dois" v-model="picked">
<label for="two">Dois</label>
<br>
<span>Escolhido: {{ picked }}</span>


Escolhido: {{ picked }}

Select

Seleção de um único item:

<select v-model="selected">
  <option disabled value="">Escolha um item</option>
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>
<br>
<span>Selecionado: {{ selected }}</span>
new Vue({
  el: '...',
  data: {
    selected: ''
  }
})

Selecionado: {{ selected }}

Se o valor inicial da expressão v-model não corresponder a nenhuma das opções, o <select> será renderizado como “não selecionado”. No iOS, isso impedirá o usuário de selecionar o primeiro item, pois não há disparo do evento change neste caso. Recomenda-se fornecer uma opção disabled com um valor vazio, como demonstrado no exemplo acima.

Seleção de múltiplos itens (vinculando a um Array):

<select v-model="selected" multiple>
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>
<br>
<span>Selecionados: {{ selected }}</span>

Selecionados: {{ selected }}

É possível renderizar dinamicamente as options com v-for:

<select v-model="selected">
  <option v-for="option in options" v-bind:value="option.value">
    {{ option.text }}
  </option>
</select>
<br>
<span>Selecionado: {{ selected }}</span>
new Vue({
  el: '...',
  data: {
    selected: 'A',
    options: [
      { text: 'Um', value: 'A' },
      { text: 'Dois', value: 'B' },
      { text: 'Três', value: 'C' }
    ]
  }
})

Selecionado: {{ selected }}

Vinculando aos Valores

Para radio, checkbox e options de select, os valores de vinculação do v-model são normalmente Strings estáticas (ou booleano no caso do checkbox):

<!-- `picked` é uma String "a" quando assinalado -->
<input type="radio" v-model="picked" value="a">

<!-- `toggle` é verdadeiro ou falso -->
<input type="checkbox" v-model="toggle">

<!-- `selected` é uma String "abc" se a primeira opção está selecionada -->
<select v-model="selected">
  <option value="abc">ABC</option>
</select>

Mas, às vezes, podemos querer vincular o valor de uma propriedade dinâmica disponível na instância Vue. Podemos usar v-bind para alcançar este objetivo. Além disso, usar v-bind nos permite vincular o valor de inputs para valores não-String.

Checkbox

<input
  type="checkbox"
  v-model="toggle"
  true-value="sim"
  false-value="não"
>
// quando está assinalado:
vm.toggle === 'sim'
// quando não está assinalado:
vm.toggle === 'não'

Os atributos true-value e false-value não afetam o atributo value do input, pois os navegadores não incluem caixas não assinaladas na submissão de formulários. Para garantir que um dos dois valores seja submetido em um formulário (ou seja, “sim” ou “não”), utilize inputs do tipo radio no lugar.

Radio

<input type="radio" v-model="pick" v-bind:value="a">
// quando está assinalado:
vm.pick === vm.a

Select

<select v-model="selected">
  <!-- Objeto literal atribuído para demonstração -->
  <option v-bind:value="{ number: 123 }">123</option>
</select>
// quando está assinalado:
typeof vm.selected // => 'object'
vm.selected.number // => 123

Modificadores

.lazy

Por padrão, v-model sincroniza o elemento com os dados após cada evento do tipo input (com exceção para o caso de composição IME descrito anteriormente). Mas adicionando o modificador lazy, a sincronização ocorrerá após o evento change:

<!-- sincronizado depois do "change" ao invés de "input" -->
<input v-model.lazy="msg">

.number

Se você quiser que a entrada do usuário seja automaticamente convertida para Number, pode adicionar o modificador number ao v-model do elemento:

<input v-model.number="age" type="number">

Isso é bastante útil, porque mesmo no caso de type="number", o valor retornado pelo HTML é sempre uma String. Se o valor não puder ser convertido através de parseFloat(), o valor original é retornado.

.trim

Se você quiser que a entrada do usuário seja automaticamente isenta de espaços no início e no fim do texto, você pode adicionar o modificador trim ao v-model do elemento:

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

v-model com Componentes

Se você não está familiarizado com componentes Vue, pode pular isto por enquanto.

Os tipos de input nativos do HTML nem sempre atendem todas as necessidades. Por sorte, componentes Vue permitem construir inputs reutilizáveis com comportamento completamente personalizado. Estes componentes também funcionam com v-model!

Para saber mais, leia sobre inputs customizados no guia de Componentes.