# การจัดการ Form Input และ Validation
ในการสร้าง component ที่เป็น form input เพื่อรับข้อมูลจากผู้ใช้ เพื่อที่จะนำข้อมูลเหล่านั้นไปประมวลผลต่อยัง Backend Service ต่าง ๆ นั้น จำเป็นต้องมีการตรวจสอบข้อมูลในฟอร์มเบื้องต้นก่อน เพื่อให้แน่ใจว่าข้อมูลที่จำเป็นนั้น ถูกกรอกมาอย่างครบถ้วนในฟอร์ม
- Catch up การบ้าน week 10
- ปรับแต่ง wk08-xxx ซึ่งบทเรียนนี้จะทำการสร้าง form input และใช้ vuelidate ในการทำ validation
- ติดตั้ง vuelidate เพื่อใช้สำหรับการทำ form input validation
- สร้างหน้า Login สำหรับรับข้อมูล username และ password และตั้งค่า vuelidate ในหน้า Login เพื่อตรวจสอบ input จาก user
# แบบฝึกหัด
# 1. Catch up การบ้าน week 10
ไม่มี
# 2. ติดตั้ง vuelidate เพื่อใช้สำหรับการทำ form input validation
Vuelidate เป็น model-based validation สำหรับ Vue.js ซึ่งสามารถนำมาใช้ในการทำ form input validation ได้โดยมีขั้นตอนดังต่อไปนี้
- ติดตั้ง vuelidate ผ่าน yarn
yarn add vuelidate
1
- สร้างไฟล์ vuelidate.js ในโฟล์เดอร์ src/plugins โดยมีข้อมูลดังภาพ (สังเกตได้ว่า เป็นเพียงการ import และเรียก Vue.use() เพื่อให้ Vue instance รู้จัก)
import Vue from "vue";
import Vuelidate from "vuelidate";
Vue.use(Vuelidate);
1
2
3
4
5
2
3
4
5
- แก้ไขไฟล์ main.js เพื่อ import ไฟล์ vuelidate.js ที่สร้างขึ้นในขั้นตอนที่แล้ว (บรรทัดที่ 8) จากนั้นเราก็สามารถที่จะเรียกใช้งาน vuelidate ได้ในทุก components
import Vue from "vue";
import App from "./App.vue";
import { store } from "./store";
import { router } from "./router";
import "./plugins/buefy-vue";
import "./plugins/vuelidate";
Vue.config.productionTip = false;
new Vue({
render: h => h(App),
store,
router,
}).$mount("#app");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 3. สร้างหน้า Login สำหรับรับข้อมูล username และ password และตั้งค่า vuelidate ในหน้า Login เพื่อตรวจสอบ input จาก user
ในขั้นตอนนี้จะทำการสร้าง vue component สำหรับใช้เป็น Login page และจะใช้ vuelidate ในการตรวจสอบค่า input ว่าถูกต้องตามที่กำหนดหรือไม่ โดยมีขั้นตอนดังต่อไปนี้
- สร้างไฟล์ LoginPage.vue ในโฟล์เดอร์ components ดังภาพด้านล่าง
- LoginPage component ประกอบไปด้วย NavBar component (บรรทัดที่ 3)
- ส่วนของ input form ที่มีช่องให้ใส่ username, password และปุ่ม submit กับ reset (บรรทัดที่ 4-27)
- สำหรับบรรทัดที่ 28-33 จะเอาไว้แสดง runtime variables ของ vuelidate เพื่อให้เข้าใจง่ายยิ่งขึ้น
- ในการตั้งค่าใช้งาน vuelidate นั้นจะต้องทำการ import validators ที่ต้องการจะใช้ก่อน ตัวอย่างนี้ใช้ required และ between (บรรทัดที่ 39)
- จากนั้นสร้าง validations attribute ให้ component (บรรทัดที่ 53) ซึ่งได้สร้าง object ชื่อ form ที่มีฟิลด์ username กับ password โดย assign required กับ between validators เพื่อกำหนดว่าสองฟิลด์นี้จำเป็นต้องกรอก และมีจำนวนตัวอักษรตามที่กำหนด (บรรทัดที่ 56 และ 60)
- สร้าง method touch() เพื่อบอก vuelidate ว่า form ถูกใส่ข้อมูลผ่าน $touch() (ดูบรรทัดที่ 66)
- สร้าง method reset() เพื่อบอก vuelidate ให้ reset การ validate ทั้งหมด (ดูบรรทัดที่ 69)
- ในการกำหนดให้ vuelidate ทำงานจะต้องตั้งค่าตัวแปรทั้งที่ form, data function และ validations attribute ให้ตรงกัน ซึ่งในที่นี้คือ
form : {username: "", password: ""}
- ใน input form ให้กำหนดที่ v-model
- ใน data function ให้
return {}
ให้ตรงกัน - ใน validations attribute สามารถกำหนด validators ให้แต่ละฟิลด์ได้ เช่น
username: {required, minLength: minLength(8)}
- ในขั้นถัดมา จะต้องทำการแสดงผลการ validate เพื่อให้ user ทราบว่าข้อมูลที่กรอกมานั้นไม่ตรงตามค่าที่กำหนดใดบ้าง
- ตัวอย่างนี้ใช้
<b-message></b-message>
ในการแสดงผล - ตัวแปร runtime ของ vuelidate ที่ใช้ในเบื้องต้นคือ
$v.form.$dirty
กับ$v.form.$invalid
เพื่อเช็คว่า form ถูกกรอกข้อมูลหรือยังและข้อมูลนั้นผ่าน validation rules หรือไม่ จากนั้นจึงใช้v-if
มาช่วยในการแสดง message (ดูบรรทัดที่ 10) - นอกจากนี้สามารถใช้
$v.form.username.required
เพื่อเช็คว่าข้อมูลที่ได้ถูกกรอกแล้วหรือไม่ - ต่อด้วย
$v.form.username.minLength
เพื่อเช็คว่าความยาวขั้นต่ำของ input ว่าตรงหรือไม่ - จากนั้นให้แสดงผลแจ้ง user ด้วย
v-if
ดังตัวอย่างในบรรทัดที่ 11, 16, 17 และ 21 - สามารถเช็ค runtime variable ของ vuelidate จากบรรทัดที่ 28-33 ผ่านหน้า LoginPage
- ตัวอย่างนี้ใช้
<template>
<div class="card-content">
<nav-bar></nav-bar>
<b-field label="Username" expanded>
<b-input v-model="form.username" maxlength="30" expanded></b-input>
</b-field>
<b-field label="Password" expanded>
<b-input type="password" v-model="form.password" maxlength="16" password-reveal></b-input>
</b-field>
<b-field v-if="$v.form.$dirty && $v.form.$invalid">
<b-message type="is-danger" has-icon v-if="!$v.form.username.required">กรุณาใส่ชื่อผู้ใช้</b-message>
<b-message
type="is-danger"
has-icon
v-if="!$v.form.username.minLength"
>ชื่อผู้ใช้ต้องไม่น้อยกว่า 8 ตัวอักษร</b-message>
<b-message type="is-danger" has-icon v-if="!$v.form.password.required">กรุณาใส่รหัสผ่าน</b-message>
<b-message
type="is-danger"
has-icon
v-if="!$v.form.password.minLength"
>รหัสผ่านต้องไม่น้อยกว่า 4 ตัวอักษร</b-message>
</b-field>
<b-field class="buttons" grouped>
<b-button type="is-primary" @click="touch">Login</b-button>
<b-button type="is-primary" @click="reset">Reset</b-button>
</b-field>
<p>Dirty : {{ $v.form.$dirty }}</p>
<p>Invalid : {{ $v.form.$invalid }}</p>
<p>Require username: {{ $v.form.username.required }}</p>
<p>User name minLength 8: {{ $v.form.username.minLength }}</p>
<p>Require password: {{ $v.form.password.required }}</p>
<p>Password minLength 4: {{ $v.form.password.minLength }}</p>
</div>
</template>
<script>
import NavBar from "./NavBar.vue";
import { required, between } from "vuelidate/lib/validators";
export default {
components: {
NavBar
},
data() {
return {
form: {
username: "",
password: ""
}
};
},
validations: {
form: {
username: {
required,
minLength: minLength(8)
},
password: {
required,
minLength: minLength(4)
}
}
},
methods: {
touch() {
this.$v.form.$touch();
},
reset() {
this.$v.form.$reset();
}
}
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
- แก้ไขไฟล์ src/route/index.js เพื่อเพิ่ม LoginPage.vue ไว้เป็นหน้า Home
import Vue from "vue";
import VueRouter from "vue-router";
import Ex01Page from "../components/ex01/Ex01Page.vue";
import Ex02Page from "../components/ex02/Ex02Page.vue";
import Ex03Page from "../components/ex03/Ex03Page.vue";
import LoginPage from "../components/LoginPage.vue";
Vue.use(VueRouter);
const routeList = [
{
path: "/",
component: LoginPage,
},
...
];
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 4. ทบทวน
- ทดลองใส่ validators อื่น ๆ เพิ่ม Builtin validators (opens new window)
- แก้ไข wk07-xxx โดยใส่ vuelidate เพื่อตรวจสอบการกรอกข้อมูลในเบื้องต้น
# 5. ส่งงาน
- Push งานขึ้นบน GitHub ตาม repository ของแต่ละคน โดยใส่ commit msg ว่า "Week 11 - Homework"
# เอกสารอ้างอิง
- [1] Model-based Form Validation with Vue.js and Vuelidate (opens new window)
- [2] Template-Based Form Validation with Vue.js and vee-validate (opens new window)
- [3] Vuelidate: Rethinking Validations for Vue.js (opens new window)
- [4] Vuelidate: Simple, lightweight model-based validation for Vue.js 2.0 (opens new window)
# Trouble Shooting
- วิธีแก้ปัญหากรณี Buefy ไม่แสดง icon ให้แทรกบรรทัดด้านล่าง ไว้ในไฟล์ public/index.html ระหว่าง tag
<head></head>
<!DOCTYPE html>
<html lang="en">
<head>
...
<link rel="stylesheet" href="https://cdn.materialdesignicons.com/2.5.94/css/materialdesignicons.min.css">
...
</head>
<body>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10