Skip to content

Binding dat z formulářů

Při práci s formuláři na frontendu často potřebujeme synchronizovat stav vstupních polí formuláře s odpovídajícím stavem v JavaScriptu. Ruční binding hodnot a změny event listenerů mohou být těžkopádné:

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

Direktiva v-model nám pomáhá výše uvedené zjednodušit na:

template
<input v-model="text">

Navíc může být v-model použita i na další druhy vstupů, elementy <textarea><select>. Automaticky se navazuje na různé DOM atributy a páry událostí podle toho, na jakém elementu je použita:

  • Element <input> s textovými typy a <textarea> používá atribut value a událost input;
  • <input type="checkbox"> a <input type="radio"> používá atribut checked a událost change;
  • <select> používá atribut value a událost change.

Poznámka

v-model bude ignorovat výchozí atributy value, checked či selected nalezené na jakýchkoli prvcích formuláře. Vždy bude za zdroj pravdy považovat aktuální binding JavaScript stavu. Počáteční hodnotu byste měli deklarovat na straně JavaScriptu pomocí proměnné dataReactivity API.

Základní použití

Text

template
<p>Zpráva je: {{ message }}</p>
<input v-model="message" placeholder="editovat" />

Zpráva je:

Poznámka

U jazyků, které vyžadují IME (čínština, japonština, korejština atd.), si všimnete, že v-model se během IME kompozice neaktualizuje. Chcete-li na tyto aktualizace také reagovat, použijte svůj vlastní input event listener a binding na value namísto použití v-model.

Víceřádkový text

template
<span>Víceřádkový text je:</span>
<p style="white-space: pre-line;">{{ message }}</p>
<textarea v-model="message" placeholder="napište více řádek"></textarea>
Víceřádkový text je:

Pozor na to, že uvnitř <textarea> nefunguje interpolace. Použitje místo toho v-model.

template
<!-- špatně -->
<textarea>{{ text }}</textarea>

<!-- dobře -->
<textarea v-model="text"></textarea>

Checkbox

Jednoduchý checkbox s proměnnou typu boolean:

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

Můžeme také provést binding více checkboxů na stejné pole resp. Set:

js
const checkedNames = ref([])
js
export default {
  data() {
    return {
      checkedNames: []
    }
  }
}
template
<div>Zaškrtnutá jména: {{ 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>
Zaškrtnutá jména: []

V tomto případě bude pole checkedNames vždy obsahovat hodnoty z aktuálně zaškrtnutých políček.

Radio

template
<div>Vybráno: {{ picked }}</div>

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

<input type="radio" id="two" value="Two" v-model="picked" />
<label for="two">Dva</label>
Vybráno:

Select

Jednoduchý výběr:

template
<div>Vybráno: {{ selected }}</div>

<select v-model="selected">
  <option disabled value="">Prosím, vyberte jednu možnost</option>
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>
Vybráno:

Poznámka

Pokud počáteční hodnota v-model výrazu neodpovídá žádné z možností, element <select> se vykreslí ve stavu „unselected“. Na iOS to způsobí, že uživatel nebude moci vybrat první položku, protože iOS v tomto případě nevyvolá událost změny. Doporučuje se proto poskytnout „disabled“ volbu s prázdnou hodnotou, jak je ukázáno v příkladu výše.

Vícenásobný výběr (binding na pole):

template
<div>Vybráno: {{ selected }}</div>

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

Volby pro <select> mohou být vykresleny dynamicky pomocí v-for:

js
const selected = ref('A')

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

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

Binding hodnot

Pro volby elementů <radio>, <checkbox> a <select> jsou hodnoty vázané přes v-model binding většinou statický string (nebo v případě checkboxu boolean):

template
<!-- `picked` je po výběru string "a" -->
<input type="radio" v-model="picked" value="a" />

<!-- `toggle` je buďto true nebo false -->
<input type="checkbox" v-model="toggle" />

<!-- `selected` je string "abc", pokud je vybrána první volba -->
<select v-model="selected">
  <option value="abc">ABC</option>
</select>

Někdy však můžeme chtít provést binding hodnoty s dynamickou vlastností na právě aktivní instanci. K tomu můžeme použít v-bind. Použití direktivy v-bind nám navíc umožňuje binding vstupní hodnoty na non-string hodnoty.

Checkbox

template
<input
  type="checkbox"
  v-model="toggle"
  true-value="ano"
  false-value="ne" />

true-value a false-value jsou atributy specifické pro Vue, které fungují pouze dohromady s v-model. Zde bude hodnota proměnné toggle nastavena na 'ano', když je checkbox zaškrtnutý, a na 'ne', pokud je odškrtnutý. Můžete také provést jejich binding na dynamickou hodnotu s použitím v-bind:

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

Tip

Atributy true-value a false-value nemají vliv na vstupní atribut value, protože prohlížeče nezaškrtnutá políčka při odesílání formulářů nezahrnují. Chcete-li zaručit, že ve formuláři bude odeslána jedna ze dvou hodnot (např. „ano“ nebo „ne“), použijte <radio>.

Radio

template
<input type="radio" v-model="pick" :value="prvni" />
<input type="radio" v-model="pick" :value="druha" />

Proměnná pick bude nastavena na hodnotu prvni, když je vybrána první volba, a na druha po výběru druhé.

Select

template
<select v-model="selected">
  <!-- inline object literal -->
  <option :value="{ number: 123 }">123</option>
</select>

v-model podporuje binding i na jiné, než řetězcové (string) hodnoty! Ve výše uvedeném příkladu bude po výběru možnosti proměnná selected nastavena na objekt s hodnotou { number: 123 }.

Modifikátory

.lazy

Ve výchozím nastavení v-model synchronizuje vstup s daty po každé události input (s výjimkou IME kompozice, jak je uvedeno výše). Místo toho můžete přidat modifikátorlazy k synchronizaci po události change:

template
<!-- synchronizuje se po „change“ místo „input“ -->
<input v-model.lazy="msg" />

.number

Pokud chcete, aby byl uživatelský vstup automaticky přetypován jako číslo, můžete do vašich vstupů spravovaných přes v-model přidat modifikátor number:

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

Pokud hodnotu nelze přetypovat pomocí parseFloat(), bude místo toho použita původní hodnota (string). V případě, že je vstup prázdný (například poté, co uživatel pole vyčistí), bude vrácen prázdný string. Toto chování se liší od vlastnosti DOM valueAsNumber.

Modifikátor number se aplikuje automaticky, pokud má vstupní pole atribut type="number".

.trim

Pokud chcete z uživatelského vstupu automaticky odstranit bílé znaky (whitespace), můžete do vašich vstupů spravovaných přes v-model přidat modifikátor trim:

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

v-model a komponenty

Pokud ještě nejste seznámeni s Vue komponentami, můžete toto prozatím přeskočit.

Vestavěné typy HTML vstupů nebudou vždy vyhovovat vašim potřebám. Naštěstí vám Vue komponenty umožňují vytvářet znovupoužitelné vstupy se zcela přizpůsobitelným chováním. Tyto vstupy dokonce také fungují s v-model! Chcete-li se dozvědět více, přečtěte si o bindingu přes v-model v průvodci Komponentami.

Binding dat z formulářů has loaded