Form Validation คือกระบวนการตรวจสอบความถูกต้องของฟิลด์ฟอร์มทั้งหมดก่อนส่งข้อมูลไปยังเซิร์ฟเวอร์ แตกต่างจากการตรวจสอบฟิลด์เดี่ยว Form Validation คำนึงถึงความสัมพันธ์ระหว่างฟิลด์: การยืนยันรหัสผ่าน การพึ่งพาของฟิลด์หนึ่งต่ออีกฟิลด์หนึ่ง เงื่อนไขบังคับ ตามข้อมูลจาก Google Developers, 2026 Form Validation ควรตรวจสอบฟอร์มทั้งหมดเมื่อส่งและแสดงสรุปข้อผิดพลาดทั้งหมดให้ผู้ใช้เห็น การตรวจสอบฟอร์มที่ถูกต้องช่วยเพิ่มอัตราการแปลงการลงทะเบียน 25-35% และลดจำนวนข้อผิดพลาดในการป้อนข้อมูล
ประเด็นสำคัญ
Form Validation คือกระบวนการที่รับประกันว่าข้อมูลทั้งหมดที่ผู้ใช้ป้อนในฟอร์มเป็นไปตามข้อกำหนดทางธุรกิจก่อนที่จะส่งไปยังเซิร์ฟเวอร์ การตรวจสอบฟอร์มรวมถึงการตรวจสอบแต่ละฟิลด์ทีละรายการ รวมถึงการตรวจสอบข้าม: รหัสผ่านตรงกับการยืนยันหรือไม่ มีการเลือกช่องทำเครื่องหมายอย่างน้อยหนึ่งช่องหรือไม่ ฟิลด์บังคับทั้งหมดถูกกรอกหรือไม่ วันที่ถูกต้องหรือไม่ (เช่น วันเกิดไม่อยู่ในอนาคต)
ความแตกต่างจากการตรวจสอบฟิลด์อย่างง่ายคือ Form Validation ดำเนินการกับฟอร์มเป็นหน่วยเดียว สามารถบล็อกการส่งหากฟิลด์ตามเงื่อนไขไม่ถูกกรอก หรือแสดงสรุปข้อผิดพลาดในหน้าต่างโต้ตอบ ในฟอร์มที่ซับซ้อน (การลงทะเบียน การชำระเงิน แบบสอบถาม) การตรวจสอบฟอร์มเป็นชั้นตรรกะที่แยกต่างหากซึ่งถูกทดสอบโดยอิสระจากส่วนติดต่อผู้ใช้
ตาม การวิจัย UX ของ NN Group ผู้ใช้กรอกฟอร์มสำเร็จมากกว่า 3 เท่าหากเห็นข้อผิดพลาดทันทีหลังจากส่ง แทนที่จะเห็นหลังจากแต่ละฟิลด์ทีละรายการ อย่างไรก็ตาม ผลลัพธ์ที่ดีที่สุดมาจากการผสมผสาน: การตรวจสอบฟิลด์ง่ายแบบทันที (ความยาว รูปแบบ) + การตรวจสอบสมบูรณ์เมื่อส่งสำหรับฟิลด์ข้ามและตรรกะทางธุรกิจ
การตรวจสอบฟิลด์ ตอบคำถาม: การป้อนข้อมูลในฟิลด์เฉพาะนี้ถูกต้องหรือไม่? อีเมลมีรูปแบบ user@domain.com โทรศัพท์ประกอบด้วยตัวเลข รหัสผ่านยาวกว่า 6 ตัวอักษร การตรวจสอบฟิลด์เป็นอิสระ — ไม่ขึ้นอยู่กับฟิลด์อื่นและสามารถดำเนินการแบบเรียลไทม์ ผลลัพธ์: ข้อผิดพลาดสำหรับฟิลด์เฉพาะหรือไม่มีข้อผิดพลาด
การตรวจสอบฟอร์ม ตอบคำถาม: สามารถส่งฟอร์มทั้งหมดได้หรือไม่? ไม่เพียงพิจารณาแต่ละฟิลด์เท่านั้น แต่ยังรวมถึงการรวมกัน: รหัสผ่านและการยืนยันต้องตรงกัน วันที่เริ่มต้นต้องไม่ช้ากว่าวันที่สิ้นสุด ผลรวมของฟิลด์ต้องเท่ากับ 100% การตรวจสอบฟอร์มดำเนินการเมื่อส่งและส่งคืนผลลัพธ์โดยรวม: ฟอร์มถูกต้องหรือไม่
ในเชิงสถาปัตยกรรม การตรวจสอบฟิลด์ถูกวางไว้ใน ชั้น UI (fragment, ViewModel) ในขณะที่การตรวจสอบฟอร์มถูกวางไว้ใน ชั้นโดเมน (use case, interactor) ซึ่งช่วยให้สามารถนำการตรวจสอบฟอร์มไปใช้ซ้ำในส่วนประกอบ UI ต่างๆ และทดสอบโดยไม่ต้องใช้โปรแกรมจำลอง ใน Clean Architecture การตรวจสอบฟอร์มเป็นกฎทางธุรกิจ ไม่ใช่ตรรกะของ UI
| เกณฑ์ | การตรวจสอบฟิลด์ | การตรวจสอบฟอร์ม |
|---|---|---|
| วัตถุที่ตรวจสอบ | ฟิลด์เดียว | ฟิลด์ทั้งหมด + ความสัมพันธ์ |
| ช่วงเวลาดำเนินการ | แบบเรียลไทม์ / เมื่อสูญเสียโฟกัส | เมื่อส่งฟอร์ม |
| ผลลัพธ์ | ข้อผิดพลาดของฟิลด์เฉพาะ | สถานะฟอร์มโดยรวม + รายการข้อผิดพลาด |
| ชั้นสถาปัตยกรรม | ชั้น UI | ชั้นโดเมน |
มีสองแนวทางหลักสำหรับ Form Validation แนวทางแรกคือเชิงบังคับ: นักพัฒนเขียนฟังก์ชันที่ตรวจสอบแต่ละฟิลด์ตามลำดับและรวบรวมรายการข้อผิดพลาด แนวทางนี้เข้าใจง่าย แต่โค้ดจะเติบโตขึ้นทุกครั้งที่มีฟิลด์ใหม่ สำหรับฟอร์มที่มี 5 ฟิลด์ แนวทางเชิงบังคับยังสะดวก สำหรับ 15 ฟิลด์ ก็เริ่มมีปัญหา
แนวทางที่สองคือ เชิงประกาศ: กฎการตรวจสอบถูกอธิบายด้วยคำอธิบายประกอบหรือการกำหนดค่า ไลบรารีจะสำรวจฟิลด์ทั้งหมด ใช้กฎ และส่งคืนผลลัพธ์ ตัวอย่าง: คำอธิบายประกอบ @Email บนฟิลด์ emailData, @ConfirmPassword บนฟิลด์ยืนยัน แนวทางเชิงประกาศช่วยลดโค้ดการตรวจสอบลง 3-5 เท่าและทำให้อ่านง่าย
แนวทางที่สามคือ เชิงรับ โดยใช้ RxJava หรือ Kotlin Flow แต่ละฟิลด์ถูกแสดงเป็น Observable หรือ StateFlow การตรวจสอบฟอร์มสมัครรับการเปลี่ยนแปลงในทุกฟิลด์และคำนวณสถานะโดยรวมใหม่ทุกครั้งที่มีการเปลี่ยนแปลง ปุ่มส่งจะทำงานโดยอัตโนมัติเมื่อฟิลด์ทั้งหมดถูกต้อง แนวทางนี้ต้องเข้าใจการเขียนโปรแกรมเชิงรับ แต่ให้ประสบการณ์ผู้ใช้ที่ลื่นไหลที่สุด
พิจารณา ฟอร์มลงทะเบียน ที่มีสามฟิลด์: อีเมล รหัสผ่าน และการยืนยันรหัสผ่าน การตรวจสอบฟอร์มรวมถึง: การตรวจสอบอีเมลผ่าน Patterns.EMAIL_ADDRESS การตรวจสอบรหัสผ่านว่ามีความยาวอย่างน้อย 8 ตัวอักษรและมีตัวเลขอย่างน้อยหนึ่งตัว การตรวจสอบว่ารหัสผ่านและการยืนยันตรงกัน เมื่อการตรวจสอบทั้งสามผ่าน ฟอร์มจึงจะสามารถส่งได้
data class RegistrationForm(
val email: String,
val password: String,
val confirmPassword: String
)
fun validateRegistration(form: RegistrationForm): ValidationResult {
if (!Patterns.EMAIL_ADDRESS.matcher(form.email).matches())
return ValidationResult(false, "Invalid email address")
if (form.password.length < 8)
return ValidationResult(false, "Password too short")
if (form.password != form.confirmPassword)
return ValidationResult(false, "Passwords do not match")
return ValidationResult(true)
}
ในตัวอย่าง validateRegistration รับ data class ของฟอร์มและส่งคืน ValidationResult หากการตรวจสอบอย่างน้อยหนึ่งรายการล้มเหลว จะส่งคืน false พร้อมข้อความที่เกี่ยวข้อง การจัดการปุ่มส่งขึ้นอยู่กับ Result: หาก isValid = true ปุ่มจะทำงาน เพื่ออัปเดตสถานะแบบเรียลไทม์ สามารถใช้ LiveData
แนวทางเชิงรับด้วย Kotlin Flow ช่วยให้คำนวณสถานะฟอร์มใหม่โดยอัตโนมัติ แต่ละฟิลด์ถูกแสดงเป็น MutableStateFlow
Android Saripaar เป็นไลบรารีการตรวจสอบที่ได้รับความนิยมมากที่สุดสำหรับ Android สามารถใส่คำอธิบายประกอบฟิลด์และ View ได้โดยตรง: @Email, @NotEmpty, @Password(min = 8, scheme = Password.Scheme.ALPHA_NUMERIC) การตรวจสอบถูกเรียกใช้ด้วยบรรทัดเดียว validator.validate() พร้อม callback Saripaar ตั้งค่าข้อผิดพลาดโดยอัตโนมัติผ่าน setError บน EditText ไลบรารียังรองรับคำอธิบายประกอบแบบกำหนดเองสำหรับกฎทางธุรกิจเฉพาะ
RxBinding + RxJava เป็นแนวทางเชิงรับโดยไม่มีไลบรารีการตรวจสอบแยก แต่ละฟิลด์เผยแพร่การเปลี่ยนแปลงผ่าน RxTextView.textChanges() ตัวดำเนินการ combineLatest รวมฟิลด์ทั้งหมดและคำนวณสถานะโดยรวม ข้อดี: ควบคุมไปป์ไลน์การตรวจสอบได้เต็มที่ เพิ่ม debounce, throttle, filter ได้ ข้อเสีย: ต้องมีความรู้เกี่ยวกับ RxJava
Material Design Components รองรับ TextInputLayout และ TextInputEditText ในตัว ไลบรารีไม่ได้ให้การตรวจสอบโดยตรง แต่ให้ส่วนติดต่อผู้ใช้สำหรับแสดงข้อผิดพลาด: setError(), setHelperText(), setCounterEnabled() สำหรับการตรวจสอบ ยังคงต้องใช้ตรรกะด้วยตนเองหรือ Saripaar Material Components รับผิดชอบการแสดงผล ไม่ใช่การตรวจสอบ
ข้อผิดพลาดแรกคือ การตรวจสอบเฉพาะฝั่งไคลเอ็นต์ Form Validation บนฝั่งไคลเอ็นต์มีไว้สำหรับประสบการณ์ผู้ใช้ ไม่ใช่เพื่อความปลอดภัย ผู้โจมตีสามารถส่งคำขอไปยัง API โดยตรง หลีกเลี่ยงการตรวจสอบ เซิร์ฟเวอร์ต้องตรวจสอบฟิลด์ทั้งหมดอีกครั้ง การตรวจสอบฝั่งไคลเอ็นต์ไม่ควรเป็นเพียงการป้องกันเดียว — เป็นชั้นเพิ่มเติมสำหรับความสะดวกของผู้ใช้ ไม่ใช่เพื่อความปลอดภัยของข้อมูล
ข้อผิดพลาดที่สองคือ การบล็อกปุ่มส่งโดยไม่มีข้อความ หากปุ่มไม่ทำงาน ผู้ใช้ควรเห็นว่าฟิลด์ใดต้องแก้ไข ปุ่มสีเทาที่ไม่มีคำอธิบายเป็นสาเหตุทั่วไปที่สุดประการหนึ่งของอัตราการแปลงฟอร์มต่ำ แสดงข้อผิดพลาดของฟิลด์ข้างๆ เสมอ แม้ว่าปุ่มจะถูกปิดใช้งาน ผู้ใช้ต้องเข้าใจว่าอะไรขัดขวางการส่งอย่างแท้จริง
ข้อผิดพลาดที่สามคือ การละเลยการตรวจสอบข้ามฟิลด์ การตรวจสอบแต่ละฟิลด์ทีละรายการไม่เพียงพอ ฟิลด์สามารถพึ่งพาซึ่งกันและกัน: รหัสผ่านและการยืนยัน วันที่เริ่มต้นและวันที่สิ้นสุด ประเทศและเมือง Form Validation ต้องตรวจสอบความสัมพันธ์เหล่านี้ การตรวจสอบเฉพาะฟิลด์แต่ละฟิลด์สร้างความรู้สึกปลอดภัยที่ผิดพลาด — ฟอร์มอาจถูกส่งด้วยข้อมูลที่ไม่สอดคล้องกัน
| ข้อผิดพลาด | ผลกระทบ | วิธีแก้ไข |
|---|---|---|
| ตรวจสอบเฉพาะฝั่งไคลเอ็นต์ | ช่องโหว่ด้านความปลอดภัย | ตรวจสอบฝั่งเซิร์ฟเวอร์บังคับ |
| ปุ่มไม่มีข้อความ | อัตราการแปลงฟอร์มต่ำ | แสดงข้อผิดพลาดฟิลด์ |
| ไม่มีการตรวจสอบข้าม | ข้อมูลไม่สอดคล้องกัน | ตรวจสอบความสัมพันธ์ฟิลด์ |
| ตรวจสอบบ่อยเกินไป | ทำให้ผู้ใช้รำคาญ | Debounce และตรวจสอบเมื่อเสียโฟกัส |
คำถามที่พบบ่อย
การตรวจสอบฟิลด์ ตรวจสอบค่าเดียวกับข้อกำหนดรูปแบบหรือความยาว Form Validation ตรวจสอบฟิลด์ทั้งหมดร่วมกัน รวมถึงการตรวจสอบข้าม: การจับคู่รหัสผ่าน การพึ่งพาของฟิลด์ การตรวจสอบฟิลด์ดำเนินการในชั้น UI, Form Validation — ในชั้นโดเมนเป็นกฎทางธุรกิจ
ใช้ แนวทางเชิงรับ: รวมฟิลด์ทั้งหมดเป็น Flow หรือ Observable เดียวและสมัครรับการเปลี่ยนแปลง ทุกครั้งที่มีการเปลี่ยนแปลงในฟิลด์ใดๆ ให้คำนวณสถานะฟอร์มโดยรวมใหม่ หากสถานะถูกต้อง — ปุ่มทำงาน ใช้ Kotlin Flow กับ combine หรือ RxJava กับ combineLatest สำหรับการอัปเดตอัตโนมัติ
Android Saripaar เป็นตัวเลือกที่ดีที่สุดสำหรับการตรวจสอบเชิงประกาศด้วยคำอธิบายประกอบ หากโปรเจกต์ใช้ RxJava — RxBinding ให้แนวทางเชิงรับโดยไม่มีไลบรารีแยกต่างหาก สำหรับฟอร์มง่าย การตรวจสอบด้วยตนเองด้วย Patterns และ TextUtils โดยไม่มีการพึ่งพาภายนอกก็เพียงพอ
จำเป็นอย่างยิ่ง การตรวจสอบฝั่งไคลเอ็นต์ปรับปรุงประสบการณ์ผู้ใช้แต่ไม่ได้ให้ความปลอดภัย เซิร์ฟเวอร์ต้องตรวจสอบข้อมูลทั้งหมดอีกครั้งเนื่องจาก API สามารถเข้าถึงได้โดยตรง อย่าพึ่งพาเฉพาะการตรวจสอบฝั่งไคลเอ็นต์เพื่อป้องกันข้อมูลที่ไม่ถูกต้องหรือเป็นอันตราย
ใน Jetpack Compose ใช้ Kotlin Flow หรือ StateFlow เพื่อเก็บสถานะของแต่ละฟิลด์ ฟังก์ชันตรวจสอบรับสถานะฟอร์มและส่งคืน ValidationResult ปุ่มส่งสมัครรับสถานะโดยรวม สำหรับการแสดงข้อผิดพลาด ใช้ isError ใน OutlinedTextField หรือ TextField ของ Compose
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม