# Interligações em Formulários

Aprenda a trabalhar com inputs de formulário com uma aula gratuita da Vue School

# Uso Básico

Você pode usar a diretiva v-model para criar interligações de dados de mão dupla (two-way data binding) em elementos input, textarea e select de formulários. Ela, automaticamente, escolhe a maneira correta de atualizar o elemento baseado no tipo do input. Embora um pouco mágica, v-model é, essencialmente, uma forma simplificada (syntax sugar) para atualizar dados nos eventos de entrada do usuário, além de cuidado especial com casos extremos.

Nota

v-model irá ignorar o estado inicial dos atributos value, checked ou selected encontrado em qualquer elemento de formulário. Ela sempre irá tratar os dados da instância ativa como a fonte de informação (source of truth). Você pode declarar o valor inicial no lado do JavasScript, dentro da opção data de seu componente.

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

  • elementos text e textarea usam a propriedade value e o evento input;
  • checkboxes e radiobuttons utilizam a propriedade checked e o evento change;
  • campos de seleção utilizam value como propriedade e change como um evento.

Nota

Você pode notar que v-model não é atualizada durante a composição através de um editor de método de entrada (IME (opens new window)), como em Chinês, Japonês, Coreano, etc. Se você também quiser responder a essas atualizações, use diretamente um evento de input e value vinculado ao invés da v-model.

# Input

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

Veja o exemplo Lidando com Fomulários: v-model simples por vuejs-br (@vuejs-br) no CodePen.

# 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>
1
2
3
4

Veja o exemplo Lidando com Formulários: textarea por vuejs-br (@vuejs-br) no CodePen.

Interpolação em textareas (<textarea></textarea>) não funcionará. Em vez disso, use v-model.

<!-- ruim -->
<textarea>{{ text }}</textarea>

<!-- bom -->
<textarea v-model="text"></textarea>
1
2
3
4
5

# Checkbox

Caixa de seleção única, valor do tipo boolean:

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

Veja o exemplo Lidando com Formulários: checkbox por vuejs-br (@vuejs-br) no CodePen.

Múltiplos checkboxes, associados ao mesmo array:

<div id="v-model-multiple-checkboxes">
  <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 selecionados: {{ checkedNames }}</span>
</div>
1
2
3
4
5
6
7
8
9
10
Vue.createApp({
  data() {
    return {
      checkedNames: []
    }
  }
}).mount('#v-model-multiple-checkboxes')
1
2
3
4
5
6
7

Veja o exemplo Lidando com Formulários: múltiplos checkboxes por vuejs-br (@vuejs-br) no CodePen.

# Radio

<div id="v-model-radiobutton">
  <input type="radio" id="one" value="Primeiro" v-model="picked" />
  <label for="one">Um</label>
  <br />
  <input type="radio" id="two" value="Segundo" v-model="picked" />
  <label for="two">Dois</label>
  <br />
  <span>Escolhido: {{ picked }}</span>
</div>
1
2
3
4
5
6
7
8
9
Vue.createApp({
  data() {
    return {
      picked: ''
    }
  }
}).mount('#v-model-radiobutton')
1
2
3
4
5
6
7

Veja o exemplo Lidando com Formulários: radiobutton por vuejs-br (@vuejs-br) no CodePen.

# Select

Seleção de um único item:

<div id="v-model-select" class="demo">
  <select v-model="selected">
    <option disabled value="">Escolha um</option>
    <option>A</option>
    <option>B</option>
    <option>C</option>
  </select>
  <span>Selecionado: {{ selected }}</span>
</div>
1
2
3
4
5
6
7
8
9
Vue.createApp({
  data() {
    return {
      selected: ''
    }
  }
}).mount('#v-model-select')
1
2
3
4
5
6
7

Veja o exemplo Lidando com Formulários: select por vuejs-br (@vuejs-br) no CodePen.

Nota

Se o valor inicial da expressão v-model não corresponder a nenhuma das opções, o elemento <select> será renderizado em um estado "não selecionado". No iOS, isso impedirá o usuário de selecionar o primeiro item, já que, neste caso, não há disparo do evento change. Portanto, é recomendado fornecer uma opção desabilitada 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>Selecionado: {{ selected }}</span>
1
2
3
4
5
6
7

Veja o exemplo Lidando com Formulários: seleção de múltiplos itens (vinculando a um array) por vuejs-br (@vuejs-br) no CodePen.

Renderização dinâmica de options com v-for:

<div id="v-model-select-dynamic" class="demo">
  <select v-model="selected">
    <option v-for="option in options" :value="option.value">
      {{ option.text }}
    </option>
  </select>
  <span>Selecionado: {{ selected }}</span>
</div>
1
2
3
4
5
6
7
8
Vue.createApp({
  data() {
    return {
      selected: 'A',
      options: [
        { text: 'Um', value: 'A' },
        { text: 'Dois', value: 'B' },
        { text: 'Três', value: 'C' }
      ]
    }
  }
}).mount('#v-model-select-dynamic')
1
2
3
4
5
6
7
8
9
10
11
12

Veja o exemplo Lidando com Formulários: select com opções dinâmicas por vuejs-br (@vuejs-br) no CodePen.

# Interligação de Valores

Para radio, checkbox e select, a interligação de valores do v-model são sempre strings estáticas (ou valores do tipo boolean, em checkboxes):

<!-- `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" quando a primeira opção for selecionada -->
<select v-model="selected">
  <option value="abc">ABC</option>
</select>
1
2
3
4
5
6
7
8
9
10

Porém, às vezes, podemos querer vincular o valor a uma propriedade dinâmica na atual instância ativa. Nós podemos utilizar v-bind para alcançar isso. Além disso, utilizando v-bind nos permite vincular o valor de um input para valores que não são uma string (non-string values).

# Checkbox

<input type="checkbox" v-model="toggle" true-value="yes" false-value="no" />
1
// quando assinalado:
vm.toggle === 'yes'
// quando não assinalado:
vm.toggle === 'no'
1
2
3
4

Dica

Os atributos true-value e false-value não afetam o atributo value dos inputs, porque os browsers não incluem caixas de seleção não assinaladas nas submissões de formulários. Para garantir que um dos dois valores seja enviado em um formulário (p. ex. "sim" ou "não"), use inputs do tipo radio.

# Radio

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

# Select

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

# Modificadores

# .lazy

Por padrão, v-model sincroniza o elemento input com os dados após cada evento input (exceto para o caso de composição IME, como descrito anteriormente). Você pode adicionar o modificador lazy para sincronizar depois do evento change:

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

# .number

Se você deseja que a entrada do usuário seja automaticamente tipificada como um Number, pode adicionar o modificador number ao v-model do elemento:

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

Isso geralmente é útil quando o tipo dp input é text. Se o tipo do input for number, o Vue pode converter automaticamente o valor bruto da string para número, e você não precisa adicionar o modificador .number ao v-model. Se o valor não puder ser convertido com parseFloat(), então o valor original é retornado.

# .trim

Se você quiser que os espaços em branco excedentes de um input sejam automaticamente removidos, é possível adicionar o modificador trim ao v-model do elemento:

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

# v-model com Componentes

Se você ainda não está familiarizado com os componentes Vue, pode pular esta parte, por enquanto.

Os tipos de input nativos do HTML nem sempre atendem as suas necessidades. Felizmente, os componentes Vue te permitem construir inputs reutilizáveis com comportamento completamente customizável. Estes componentes também funcionam com v-model! Para saber mais, leia sobre inputs customizados no guia de Componentes.