點燈坊

失くすものさえない今が強くなるチャンスよ

使用 HTML Form Validation

Sam Xiao's Avatar 2020-12-31

以前 Form Validation 要完全使用 JavaScript,HTML 5 將常用檢查功能內建,可大幅減少 JavaScript 長度。

Version

HTML 5

HTML 5

validate000

當沒有任何輸入時,按下 Submit 會出現警告訊息。

validate001

當輸入字串長度小於 5 時,按下 Submit 也會出現警告訊息。

validate002

當有輸入字串且長度大於 5 時,才會觸發原本的 submit event。

<template>
  <form @submit.prevent="onSubmit">
    <input ref="username" @invalid.capture.prevent="onInvalid" required minlength="5">
    <button>Submit</button>
    <p>{{ msg }}</p>
  </form>
</template>

<script>
let onSubmit = function() {
  this.msg = 'Submit event fired'
}

let onInvalid = function() {
  if (this.$refs.username.validity.valueMissing)
    this.msg = 'User name is required'
  else if (this.$refs.username.validity.tooShort)
    this.msg = 'User name is too short'
}

export default {
  name: "App",
  data: () => ({
    msg: ''
  }),
  methods: {
    onSubmit,
    onInvalid
  }
}
</script>

第 2 行

<form @submit.prevent="onSubmit">
  <input ref="username" @invalid.capture.prevent="onInvalid" required minlength="5">
  <button>Submit</button>
  <p>{{ msg }}</p>
</form>

若要使用 HTML 5 Form Validation,則 <input> 必須放在 <form> 內,且不能使用 <button>click event,而要使用 <form>submit event。

<form @submit.prevent="onSubmit">

<form>submit event 預設會 post 到 server,因為現在會使用 Ajax 打 RESTful API,因此會在 @submit 加上 prevent modifier 避免 <form> post 到 server,相當於 event.preventDefault()

<input ref="username" @invalid.capture.prevent="onInvalid" required minlength="5">

由於我們想判斷 <input>必填長度需大於 5,使用了 HTML 5 的 requiredminlength="5" attribute。

HTML 5 判斷時會觸發 invalid event,且會在 <input> 以 popup 顯示預設錯誤訊息,但因為我們只想借用 HTML 5 Form Validation,並不想以 popup 顯示,因此使用了 invalid.capture.prevent

  • capture:原本的 HTML 5 會先由內而外觸發 popup event 然後才是 invalid event,為了阻擋 popup 顯示,特別使用 capture modifier 改成由外向內先觸發 invalid event,如此才能避免 popup 顯示。
  • prevent:為了避免 invalid event 執行完又觸發 popup event,因此使用 prevent modifier 避免 invalid event 執行完後繼續執行 popup event。

HTML 5 主要以 element 控制,而非 Vue 的 model-driven 寫法,因此特別加上 ref="username",稍後將以 username 控制 <input> element。

14 行

let onInvalid = function() {
  if (this.$refs.username.validity.valueMissing)
    this.msg = 'User name is required'
  else if (this.$refs.username.validity.tooShort)
    this.msg = 'User name is too short'
}

HTML 5 允許我們由 element 的 validity.valueMissingvalidity.tooShort 判斷 requiredminlength="5" 是否成立。

由於 validity 是在 <input> element 下,因此必須透過 this.$refs.username 取得 <input>

第 10 行

let onSubmit = function() {
  this.msg = 'Submit event fired'
}

invalid event 都沒錯時,才會執行 submit event 完成 Form Validation。

Conclusion

  • 可發現 HTML 5 Form Validation 寫法非常繁瑣,除了須小心控制 event 外,還必須小心處理 element,更可發現 Vue 的 model-driven 寫法之精簡
  • 若要使用原生 DOM 寫法,則必須搭配 $refs 取得 element