v-model tạo two-way binding giữa form input và state. Trong AEM, dùng cho các form phía client (search bar, filter, contact form) nằm trong component Vue mount lên DOM HTL render.
Bản chất v-model
v-model là cú pháp rút gọn của việc bind value cộng lắng nghe event cập nhật. Vue tự chọn property và event phù hợp theo loại input:
Text và textarea
<input v-model="message" placeholder="edit me">
<p>Message: {{ message }}</p>
<textarea v-model="message"></textarea>
Nội suy bên trong textarea không hoạt động: <textarea>{{ text }}</textarea> sai. Phải dùng v-model.
Checkbox
Một checkbox đơn bind giá trị boolean:
<input type="checkbox" id="agree" v-model="checked">
<label for="agree">{{ checked }}</label>
Nhiều checkbox cùng bind vào một mảng:
<input type="checkbox" value="Jack" v-model="checkedNames">
<input type="checkbox" value="John" v-model="checkedNames">
<input type="checkbox" value="Mike" v-model="checkedNames">
<span>Checked: {{ checkedNames }}</span>
data() {
return { checkedNames: [] }
}
Radio
<input type="radio" value="One" v-model="picked">
<input type="radio" value="Two" v-model="picked">
<span>Picked: {{ picked }}</span>
Select
Single select. Nên có một option disabled với value rỗng làm placeholder, tránh lỗi trạng thái unselected trên iOS.
<select v-model="selected">
<option disabled value="">Chọn một mục</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
data() {
return { selected: '' }
}
Multiple select bind vào mảng:
<select v-model="selected" multiple>
<option>A</option>
<option>B</option>
</select>
Option động render bằng v-for:
<select v-model="selected">
<option v-for="opt in options" :value="opt.value" :key="opt.value">
{{ opt.text }}
</option>
</select>
data() {
return {
selected: 'A',
options: [
{ text: 'One', value: 'A' },
{ text: 'Two', value: 'B' }
]
}
}
Value bindings
Mặc định v-model bind giá trị tĩnh (string với radio, boolean với checkbox). Cần bind giá trị động hoặc kiểu khác thì dùng các attribute sau.
Checkbox với giá trị tùy chỉnh:
<input type="checkbox" v-model="toggle" true-value="yes" false-value="no">
Khi checked thì toggle === 'yes', khi unchecked thì toggle === 'no'. Lưu ý true-value/false-value không ảnh hưởng attribute value thật, nên unchecked box không được gửi trong form submit. Cần đảm bảo gửi một trong hai giá trị thì dùng radio.
Radio bind giá trị động:
<input type="radio" v-model="pick" :value="a">
Select option bind object:
<select v-model="selected">
<option :value="{ number: 123 }">123</option>
</select>
Modifiers
<input v-model.lazy="msg">
<input v-model.number="age" type="number">
<input v-model.trim="msg">
Lưu ý .number: input HTML luôn trả về string kể cả khi type="number", nên cần .number nếu muốn nhận kiểu Number trong state.
Tips cho AEM
Endpoint hoặc cấu hình lấy từ Sling Model qua data attribute, state form quản lý bằng v-model.
<!-- HTL mount point -->
<div id="contact" data-endpoint="${model.formEndpoint}"></div>
new Vue({
el: '#contact',
data() {
return {
endpoint: this.$el.dataset.endpoint,
form: { name: '', email: '', topic: '' }
}
},
methods: {
async submit() {
await fetch(this.endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(this.form)
})
}
}
})
<!-- template Vue -->
<form @submit.prevent="submit">
<input v-model.trim="form.name" placeholder="Tên">
<input v-model.trim="form.email" type="email" placeholder="Email">
<select v-model="form.topic">
<option disabled value="">Chọn chủ đề</option>
<option>Hỗ trợ</option>
<option>Góp ý</option>
</select>
<button type="submit">Gửi</button>
</form>
Gom các field vào một object form để gửi nguyên cụm và dễ reset. Bind state nguồn vào computed có setter nếu cần biến đổi giá trị trước khi lưu.