實作紀錄:操控 DOM 來驗證報名表單


Posted by Nicolakacha on 2020-09-06

這個練習是利用 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

本練習為程式導師計畫第四期第七週作業


#DOM #javascript







Related Posts

[Windows] telnet 確定 TCP 連接埠為開啟或關閉

[Windows] telnet 確定 TCP 連接埠為開啟或關閉

[TensorFlow Certification Day2] 課程規劃與安排時間

[TensorFlow Certification Day2] 課程規劃與安排時間

[day-3]布林、undefined、null/字串數字轉換/比較與邏輯運算子

[day-3]布林、undefined、null/字串數字轉換/比較與邏輯運算子


Comments