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>
a <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á atributvalue
a událostinput
; <input type="checkbox">
a<input type="radio">
používá atributchecked
a událostchange
;<select>
používá atributvalue
a událostchange
.
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í Reactivity 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([])
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' }
])
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.