เนื้อหาตอนต่อไปนี้ เราจะมาดูเกี่ยวกับการใช้งาน Form ใน VueJS
เกี่ยวกับการจัดการข้อมูล state หรือตัวแปรข้อมูลเพื่อใช้งานร่วมกับ Form
โดยใช้ v-model directive ซึ่งเราอาจจะคุ้นตามาบ้างเล็กน้อยในตอนที่ผ่านๆ มา
การใช้งาน v-model ในฟอร์มของ Vue.js
เป็นการทำให้ฟอร์มสามารถทำงานร่วมกับข้อมูลใน data ของ Vue ได้อย่างสะดวก โดย
v-model จะทำการผูกข้อมูลสองทาง (two-way data binding) ระหว่างค่าในฟอร์มและ
ข้อมูลใน Vue instance.
ตัวอย่างการใช้งาน v-model
<script setup> import { reactive, ref } from 'vue' const formData = reactive({ name: '', email: '', message: '' }) const submitted = ref(false) function handleSubmit() { submitted.value = true console.log('Form Submitted:', formData) // ส่งข้อมูลไปยังเซิร์ฟเวอร์หรือประมวลผลตามต้องการ } </script> <template> <form @submit.prevent="handleSubmit"> <label for="name">Name:</label> <input type="text" id="name" v-model="formData.name"> <br> <label for="email">Email:</label> <input type="email" id="email" v-model="formData.email"> <br> <label for="message">Message:</label> <textarea id="message" v-model="formData.message"></textarea> <br> <button type="submit">Submit</button> </form> <div v-if="submitted"> <h3>Form Data:</h3> <p>Name: {{ formData.name }}</p> <p>Email: {{ formData.email }}</p> <p>Message: {{ formData.message }}</p> </div> </template>
ในการใช้งานฟอร์ม บ่อยคร้้งเราจำเป็นจะต้องจัดการกับข้อมูลไปพร้อมๆ กับการใช้งานฟอร์ม
ดังนั้นหากใช้วิธีการกำหนดเองตามรูปแบบที่เราเคยใช้งานผ่าน v-bind ร่วมกับ v-on ก็จะดู
เป็นการยุ่งยากและไม่สะดวกนัก ดูรูปแบบที่เราสามารถจัดการกับข้อมูลได้แบบเดิม
<script setup> import { ref } from 'vue' const text = ref('') </script> <template> <input :value="text" @input="event => text = event.target.value"> <div>{{ text }}</div> </template>
จะเห็นว่ามีการใช้งานทั้ง v-bind และ v-on เพื่อผูกข้อมูล text กับ input และเป็นวิธีที่ค่อนข้าง
ไม่สะดวกและยุ่งยาก ดังนั้น ใน vuejs จึงมี v-model มาช่วยจัดการให้ง่ายขึ้น สามารถปรับใหม่
ได้เป็นดังนี้
<script setup> import { ref } from 'vue' const text = ref('') </script> <template> <input v-model="text"> <div>{{ text }}</div> </template>
จะเห็นว่าง่ายขึ้นมาก นอกจากนี้ v-model ยังสามารถใช้กับ input ประเภทต่างๆ กัน
เช่น <textarea> หรือแม้แต่ <select> ตัว v-model จะตรวจจับและกำหนด event
ของแต่ละ element ให้โดยอัตโนมัติ โดยที่เราไม่ต้องกำหนดเอง มาดูรายละเอียดการใช้
งานของแต่ละ element เบื้องต้นกัน
การใช้งานกับ Input Text
<script setup> import { ref } from 'vue' const message = ref('') </script> <template> <p>Message is: {{ message }}</p> <input v-model="message" placeholder="edit me" /> </template>
การใช้งานกับ Textarea
<script setup> import { ref } from 'vue' const message = ref('') </script> <template> <span>Multiline message is:</span> <p style="white-space: pre-line;">{{ message }}</p> <textarea v-model="message"></textarea> <!-- ใช้รูปแบบด้านล่างนี้ {{ }} ไมได้ ต้องใช้ v-model แทน --> <!-- รูปแบบด้านล่าง สามารถใช้เพื่อนำข้อมูลไปแสดงเท่านั้น --> <textarea >{{ message }}</textarea> </template>
การใช้งานกับ Checkbox
กรณีแสดงอันเดียว และใช้ค่าเป็น boolean กับ กรณีแบบใช้แบบหลายอันพร้อมกัน
<script setup> import { ref } from 'vue' const checked = ref(false) const checkedNames = ref([]) </script> <template> <input type="checkbox" id="checkbox" v-model="checked" /> <label for="checkbox">{{ checked }}</label> <hr> <div>Checked names: {{ 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> </template>
สังเกตว่าตัวแปร checked จะเป็น ค่า boolean ในขณะที่ checkedNames จะเป็น array ของ
ข้อมูล ซึ่งในตัวอย่าง ถ้าเราเลือกรายชื่อแต่ละอัน จะเป็นการเพิมรายชื่อนั้นหรือค่าข้อมูลของ checkbox
น้้นๆ เข้าไปใน array ซึ่งรูปแบบการใช้งานข้างต้นจะสะดวกและง่ายมาก เราไม่ต้องเขียนโค้ดเพิ่มเติม
มากมายเกี่ยวกับการจัดการให้ได้ผลลัพธ์ข้างต้น
ตัวอย่างการใช้งานที่ซับซ้อนขึ้น
<script setup> import { ref } from 'vue' const fruits = ref(['Apple', 'Banana', 'Cherry', 'Date', 'Grape']) const selectedFruits = ref([]) </script> <template> <h2>Select Your Favorite Fruits</h2> <div v-for="(fruit, index) in fruits" :key="index"> <label :for="fruit"> <input type="checkbox" :id="fruit" :value="fruit" v-model="selectedFruits" /> {{ fruit }} </label> </div> <div v-if="selectedFruits.length"> <h3>Selected Fruits:</h3> <ul> <li v-for="(fruit, index) in selectedFruits" :key="index">{{ fruit }}</li> </ul> </div> </template>
การใช้งานกับ Radio
<script setup> import { ref } from 'vue' const picked = ref('') </script> <template> <div>Picked: {{ picked }}</div> <input type="radio" id="one" value="One" v-model="picked" /> <label for="one">One</label> <input type="radio" id="two" value="Two" v-model="picked" /> <label for="two">Two</label> </template>
การใช้งานกับ Select
<script setup> import { ref } from 'vue' const selected = ref('') const selected2 = ref([]) </script> <template> <div>Single Selected: {{ selected }}</div> <select v-model="selected"> <option disabled value="">Please select one</option> <option>A</option> <option>B</option> <option>C</option> </select> <hr> <div>Multiple Selected: {{ selected2 }}</div> <select :style="{width:'100px'}" v-model="selected2" multiple> <option>A</option> <option>B</option> <option>C</option> </select> </template>
กรณีที่เป็นแบบการเลือกหลายรายการ ตัวแปร state จะต้องเป็นข้อมูลประเภท array ในตัวอย่าง
seleceted2 จะเป็น array
การจัดการ Dynamic state ใน Checkbox Radio และ Select Options
ปกติแล้วข้อมูลที่ใช้กับ checkbox radio และ select option จะเป็นข้อมูลประเภทคงที่ หรือ
static (กรณี checkbox อาจมีใช้เป็น boolean) แต่กรณีที่เราต้องการใช้งานร่วมกับข้อมูล
ที่เป็นแบบ dynamic หรือมีค่าแปรเปลี่ยนได้ เราสามารถนำ v-bind มาใช้งานร่วมได้ เพื่อให้
สามารถรองรับข้อมูลที่ไม่จำเป็นต้องเป็น static อย่างเดียว
ตัวอย่างการกำหนด Value Binding ใน Checkbox
<script setup> import { ref } from 'vue' const toggle = ref('no') </script> <template> <div> <input type="checkbox" v-model="toggle" true-value="yes" false-value="no" /> <p>Toggle value: {{ toggle }}</p> </div> </template>
จะเห็นว่าเราสามารถกำหนดค่าให้กับ checkbox เป็นค่าใดๆ ก็ได้ โดยใช้ true-value และ
false-value ซึ่งเป็น attribute พิเศษเฉพาะใน vuejs เพื่อให้ค่า toggle แปรเปลี่ยนค่าได้
ซึ่งเราสามารถใช้ v-bind กำหนดและใช้ร่วมกับ dynamic value ดังนี้
<script setup> import { ref } from 'vue' const toggle = ref('no') const dynamicTrueValue = ref('yes') const dynamicFalseValue = ref('no') </script> <template> <div> <input type="checkbox" v-model="toggle" :true-value="dynamicTrueValue" :false-value="dynamicFalseValue" /> <p>Toggle value: {{ toggle }}</p> </div> </template>
ตัวอย่างการกำหนด Value Binding ใน Radio
<script setup> import { ref } from 'vue' const checked = ref(false) const checkedNames = ref([]) const first = ref('Option 1') const second = ref('Option 2') const pick = ref('') // Default value </script> <template> <div> <input type="radio" v-model="pick" :value="first" /> {{ first }} <input type="radio" v-model="pick" :value="second" /> {{ second }} <p>Selected value: {{ pick }}</p> </div> </template>
ตัวแปร pick จะมีค่าขึ้นกับการเลือก ซึ่งเป็นได้ทั้งค่าตามตัวแปร first ถ้าเลือกรายการแรก หรือ
เป็นได้ตามค่า second ถ้าเลือกตัวเลือกที่สอง
ตัวอย่างการกำหนด Value Binding ใน Select Options
<script setup> import { ref } from 'vue' const selected = ref(null) // Default value </script> <template> <div> <select v-model="selected"> <!-- ตัวอย่าง กำหนดค่าเป็น object --> <option :value="{ number: 123 }">123</option> </select> <p>Selected value: {{ selected }}</p> </div> </template>
จะสังเกตเห็นว่า v-model รองรับการใช้งานร่วมกับ v-bind ข้อมูลที่ไม่จำเป็นต้องเป็นข้อความ
อย่างเดียว แต่สามารถเป็นค่าอื่นๆ ได้ อย่างใน option ถ้าถูกเลือก ก็จะทำให้ตัว selected เป็น
object ที่มีค่าเท่ากับ { number: 123 }
รูปแบบการปรับแต่ง modifier ที่ใช้ใน v-model
ใน v-model directive ย้งรองรับรูปแบบการปรับแต่งต่างๆ ดังนี้
การใช้งาน v-model.lazy
โดยค่าเริ่มต้น v-model จะซิงค์ค่าข้อมูลกับ property ใน data เมื่อมี event input
แต่การใช้ตัวปรับแต่ง .lazy จะเปลี่ยนพฤติกรรมนี้ให้ซิงค์ใน event change แทน
การใช้งาน v-model.number
ตัวปรับแต่งนี้จะเปลี่ยนค่าที่ใส่เข้าไปให้เป็นตัวเลขโดยอัตโนมัติ ซึ่งมีประโยชน์สำหรับ input
ที่ต้องการค่าตัวเลข
การใช้งาน v-model.trim
ตัวปรับแต่งนี้จะตัดช่องว่างที่ขึ้นต้นและลงท้ายออกจากค่าที่ใส่เข้าไปโดยอัตโนมัติ ซึ่งมีประโยชน์สำหรับ input
ที่ต้องการไม่ให้มีช่องว่างเกินมาทั้งข้างหน้าและข้างหลัง
ตัวอย่างการใช้งาน
<script setup> import { ref } from 'vue' const lazyMessage = ref('') const age = ref(null) const username = ref('') </script> <template> <div> <label>Lazy: <input v-model.lazy="lazyMessage" placeholder="Type and then lose focus" /> </label> <p>Lazy message: {{ lazyMessage }}</p> <label>Number: <input v-model.number="age" placeholder="Enter a number" /> </label> <p>Age: {{ age }}</p> <label>Trim: <input v-model.trim="username" placeholder="Type your username" /> </label> <p>Username: {{ username }}</p> </div> </template>
จากตัวอย่าง การใช้งาน .lazy ปกติ หากไม่ได้ใช้งาน ถ้าเราพิมพ์ข้อความเข้าไป ช้อความที่พิมพ์
ก็จะแสดงทันที่เรากดแป้นพิมพ์ แต่เมื่อกำหนดด้วยตัวปรับแต่งที่ชื่อ .lazy จะถูกเปลี่ยนมาใช้ event
change แทน นั่นคือ หลักจากพิมพ์ เราต้องคลิกที่ว่างอื่น หรือให้หลุดโฟกัส ก่อน จึงเกิด change
event แล้ว ข้อความถึงจะแสดง
การใช้งาน .number หากเดิมไม่ได้กำหนดใช้งาน ถ้าเราพิมพ์ตัวเลข เข้าไป ค่าของ age.value
ก็จะมีค่าเป็น String ในขณะที่เราถ้าใส่ตัวปรับแต่งเข้าไป เป็น .number จะทำให้ age.value
หากพิมพ์ตัวเลขเข้าไป จะไม่เป็น string แต่จะกลายเป็น number แทน
การใช้งาน .trim เข้าใจอย่างง่ายก็คือการตัดช่องว่างหน้าหลัง ถ้ามี นั่นคือ ข้อความที่แสดง จะไม่มี
ช่องว่างด้านหน้าหรือด้านหลัง
เนื้อหาเกี่ยวกับการใช้งาน v-model ร่วมกับข้อมูลใน Form ของ vuejs เบื้องต้นก็ขอจบเพียงเท่านี้
แน่นอนว่ายังมีรายละเอียดสำคัญอื่นๆ ที่เราต้องศึกษาต่อไป รอติดตาม