這個練習是利用 JavaScript 操控 DOM 的方法來實作簡單的報名表單驗證
表單頁面是這樣的:
<body>
<form class="form">
<div class="title">
<h1>新拖延運動報名表單</h1>
<p>活動日期:2020/12/10 ~ 2020/12/11</p>
<p>活動地點:台北市大安區新生南路二段1號</p>
<p class="notice">* 必填</p>
</div>
<div class="group required txt user-name">
<label for="user-name">暱稱</label>
<input name="name" type="text" placeholder="您的回答" />
<div class="remind">請輸入暱稱</div>
</div>
<div class="group required txt user-email">
<label for="user-email">電子郵件</label>
<input name="email" type="text" placeholder="您的電子郵件" />
<div class="remind">請輸入Email</div>
<div class="remind2">請輸入正確的 Email 格式</div>
</div>
<div class="group required txt user-mobile">
<label for="user-mobile">手機號碼</label>
<input name="phone" type="text" placeholder="您的手機號碼" />
<div class="remind">請輸入手機號碼</div>
<div class="remind2">請輸入正確的手機號碼格式</div>
</div>
<div class="group required radio register-type">
<label>報名類型</label>
<label>
<input name="type" type="radio" value="1" />
<span>躺在床上用想像力實作</span>
</label>
<label>
<input name="type" type="radio" value="2" />
<span>趴在地上滑手機找現成的</span>
</label>
<div class="remind">請選擇報名類型</div>
</div>
<div class="group required txt knowing-source">
<label for="knowing-source">怎麼知道這個活動的?</label>
<input name="source" type="text" placeholder="您的回答" />
<div class="remind">請告訴我們您是怎麼知道這個活動的</div>
</div>
<div class="group optional txt other">
<div class="other">其他</div>
<h2>對活動的一些建議</h2>
<input name="other" type="text" placeholder="您的回答" />
</div>
<div class="btn-group">
<button type="submit">提交</button>
</div>
<p>請勿透過表單送出您的密碼。</p>
</form>
<footer>
<p>© 2020 © Copyright. All rights Reserved.</p>
</footer>
</body>
第一步是去監聽 form 的 submit 事件,建立一個 check 函式去卻驗證表單內容
form.addEventListener("submit", check);
在 check 這個 functino 內,宣告一個 hasError 的變數為 false,若函式內的驗證有錯時,我們就把他重新賦值為 true 來進行驗證。
let hasError = false;
我們利用 document.querySelectorAll 去爬每個欄位,把所有的欄位用變數宣告分成 text 、radio 、必填、以及提示,使用者端輸入的值先宣告為空物件。
function check(e) {
e.preventDefault();
const groups = document.querySelectorAll(".group");
const values = {};
let hasError = false;
for (group of groups) {
const isTxt = group.classList.contains("txt");
const isRadio = group.classList.contains("radio");
const isRequired = group.classList.contains("required");
const remind = group.querySelector(".remind");
const remind2 = group.querySelector(".remind2");
}
接下來就是時做各個欄位的驗證,如果任何一個欄位驗證不通過,我們就可以利用一開始宣告的變數 hasError = true 來判斷驗證不通過,並阻止提交表單。
text 欄位分成必填和非必填兩種,而必填欄位裡面的 email 和 phone 用正規表達式來驗證,其他必填欄位則是用是否有輸入內容來做驗證,若為空則顯示提醒訊息。
//輸入是 text 格式時
if (isTxt) {
const input = group.querySelector('input[type="text"]');
const inputValue = input.value.trim();
//是必填欄位時,判斷資料是否有效
if (isRequired) {
const name = group.querySelector("input").getAttribute("name");
//phone 欄位確認
if (name === "phone") {
if (isPhone(inputValue)) {
remind.classList.remove("show");
remind2.classList.remove("show");
values[input.name] = inputValue;
} else if (inputValue){
remind.classList.remove("show");
remind2.classList.add("show");
hasError = true;
} else if (!inputValue) {
remind.classList.add("show");
remind2.classList.remove("show");
hasError = true;
}
}
//email 欄位確認
else if (name === "email") {
if (isEmail(inputValue)) {
remind.classList.remove("show");
remind2.classList.remove("show");
values[input.name] = inputValue;
} else if (inputValue){
remind.classList.remove("show");
remind2.classList.add("show");
hasError = true;
} else if (!inputValue) {
remind.classList.add("show");
remind2.classList.remove("show");
hasError = true;
}
}
// 其他必填欄位有填寫時
else if (inputValue) {
remind.classList.remove("show");
values[input.name] = inputValue;
}
//必填欄位沒填寫時的處理
else if (!inputValue) {
remind.classList.add("show");
hasError = true;
}
//不是必填欄位時,若有輸入資料,就直接儲存
} else if (inputValue) {
values[input.name] = inputValue;
}
}
email 和 phone 欄位裡面我們分別用獨立的 function 利用正規表達式來做比較嚴謹的驗證
function isEmail(email) {
var regex = /^([a-zA-Z0-9_\.\-\+])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
if (!regex.test(email)) {
return false;
} else {
return true;
}
}
function isPhone(phone) {
var regex = /^09\d{2}-?\d{3}-?\d{3}$/;
if (!regex.test(phone)) {
return false;
} else {
return true;
}
}
完成了所有 text 的驗證,最一開始區分出來的 radio 欄位,因為只有一題,且為必填,所以並不用再做區分,可以判斷任一格是否有勾選成為 checked 即可
if (isRadio) {
const types = group.querySelectorAll('input[type="radio"]');
let checkType;
for (type of types) {
//若有勾選,則存取勾選項目的 value
if (type.checked) {
checkType = type;
remind.classList.remove("show");
values[type.name] = checkType.value;
}
}
//若無勾選擇出現提醒
if (!checkType) {
remind.classList.add("show");
hasError = true;
}
如果順利通過每一道驗證,我們就可以提交表單後端,這部份不是這次練習的主題所以先不會實作出來,改用 alert 替代
if (!hasError) {
alert(JSON.stringify(values));
}
這樣一個簡單的報名表單驗證就完成啦!
觀看 DEMO
本練習為程式導師計畫第四期第七週作業