【问题标题】:Check all input's validity first, then submit Vanilla JS首先检查所有输入的有效性,然后提交 Vanilla JS
【发布时间】:2022-12-29 23:25:02
【问题描述】:

我正在处理具有多个输入字段的表单页面。如果输入无效,则会显示一些错误文本。

用户正确提交所有输入字段后,我想显示一个模式。除了 CVC 输入外,表单验证工作几乎正常。它仅在 CVC 字段为空时进行检查。

我该怎么做才能解决这个问题?

const form = document.querySelector('form');
const inputs = document.querySelectorAll('input');
const modal = document.querySelector('.modal');
const modalClose = document.querySelector('.close');

form.addEventListener('submit',(e)=>{
    e.preventDefault();
    inputs.forEach(input=>{
        if(input.classList.contains('name-input')){
            containsNameInput(input)
        }else if(input.classList.contains('date')){
            containsDateInput(input)
        }else{
            containsOtherInput(input)
        }

        if(input.parentElement.classList.contains('error-empty')
        || input.parentElement.classList.contains('error-invalid')
        ||input.parentElement.parentElement.classList.contains('error-invalid')
        || input.parentElement.parentElement.classList.contains('error-empty')){
            modal.style.display = 'none';
        }else{
            modal.style.display = "block";
        }
    })
})

const containsNameInput = function(input){
    if(input.value === ''){
        input.parentElement.classList.add('error-empty');
        input.parentElement.classList.remove('error-invalid');
    }else if(input.value !== '' && input.value.match(/^[0-9]+$/) !== null){
        input.parentElement.classList.remove('error-empty');
        input.parentElement.classList.add('error-invalid');
    }
    else{
        input.parentElement.classList.remove('error-empty');
        input.parentElement.classList.remove('error-invalid');
    }
}

const containsDateInput = function(input){
    if(input.value === ''){
        input.parentElement.parentElement.classList.add('error-empty');
        input.parentElement.parentElement.classList.remove('error-invalid');
    }else if(input.value !== '' && input.value.match(/^[0-9]+$/) === null){  // wil return null if value has anything accept number
        input.parentElement.parentElement.classList.remove('error-empty');
        input.parentElement.parentElement.classList.add('error-invalid');
    }else{
        input.parentElement.parentElement.classList.remove('error-empty');
        input.parentElement.parentElement.classList.remove('error-invalid');
    }
}

const containsOtherInput = function(input){
    if(input.value === ''){
        input.parentElement.classList.add('error-empty');
        input.parentElement.classList.remove('error-invalid');
    }else if(input.value !== '' && input.value.match(/^[0-9]+$/) === null){
        input.parentElement.classList.remove('error-empty');
        input.parentElement.classList.add('error-invalid');
    }else{
        input.parentElement.classList.remove('error-empty');
        input.parentElement.classList.remove('error-invalid');
    }
}

modalClose.addEventListener('click',()=>{
    modal.style.display = "none";
})
.input-field .error{
    color: red;
    font-size: .7rem;
    display: none;
}
.input-field.error-empty .empty{
    display: block;
}
.input-field.error-invalid .invalid{
    display: block;
}
.modal{
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    display: none;
    background:white;
}
<form>
        <div class="input-field">
          <label for="name">Cardholder Name</label>
          <input type="text" placeholder="e.g. Jane Appleseed" id="name" name="name" maxlength="25" class="name-input">
          <p class="error empty">Can't be blank</p>
          <p class="error invalid">Wrong format, letters only</p>
        </div>
        <div class="input-field">
          <label for="number">Card Number</label>
          <input type="text" placeholder="e.g. 1234 5678 9123 0000" id="number" name="number" minlength="16" maxlength="16" class="number-input">
          <p class="error empty">Can't be blank</p>
          <p class="error invalid">Wrong format, numbers only</p>
        </div>
        <div class="flex-row">
          <div class="input-field date-container">
            <label id='date'>Exp. Date (MM/YY)</label>
            <div class="date-input">
              <input type='text' placeholder="MM" id='month' name="month" aria-labelledby='date' class="date month-input" maxlength="2"/>
              <input type='text' placeholder="YY" id='year' name="year" aria-labelledby='date' class="date year-input" maxlength="2"/>
            </div>
            <p class="error empty">Can't be blank</p>
            <p class="error invalid">Wrong format, numbers only</p>
          </div>
          <div class="input-field">
            <label for="cvc">CVC</label>
            <input type="text" placeholder="e.g. 123" id="cvc" name="cvc" maxlength="4" class="cvc-input">
            <p class="error empty">Can't be blank</p>
            <p class="error invalid">Wrong format, numbers only</p>
          </div>
        </div>
        <button type="submit" class="btn">Confirm</button>
      </form>
      <section class="modal">
        <img src="./images/icon-complete.svg" alt="">
        <h2>Thank you!</h2>
        <p>We've added your card details</p>
        <button type="button" class="btn close">Continue</button>
      </section>

【问题讨论】:

    标签: javascript html forms validation


    【解决方案1】:

    经典错误:结果“变量”(此处:可见性)在每次检查后都会设置,因此它将包含最后一次检查的结果而没有其他内容。相反,您应该在一开始就假设成功,并且只在检查失败时设置(并且永远不要再次设置为成功)。然后,如果任何检查失败,整个事情也会失败。

    const form = document.querySelector('form');
    const inputs = document.querySelectorAll('input');
    const modal = document.querySelector('.modal');
    const modalClose = document.querySelector('.close');
    
    form.addEventListener('submit', (e) => {
      e.preventDefault();
      modal.style.display = "block"; // assume things go well
      inputs.forEach(input => {
        if (input.classList.contains('name-input')) {
          containsNameInput(input)
        } else if (input.classList.contains('date')) {
          containsDateInput(input)
        } else {
          containsOtherInput(input)
        }
    
        if (input.parentElement.classList.contains('error-empty') ||
          input.parentElement.classList.contains('error-invalid') ||
          input.parentElement.parentElement.classList.contains('error-invalid') ||
          input.parentElement.parentElement.classList.contains('error-empty')) {
          modal.style.display = 'none'; // act when they do not
          //        }else{
          //            modal.style.display = "block";
        }
      })
    })
    
    const containsNameInput = function(input) {
      if (input.value === '') {
        input.parentElement.classList.add('error-empty');
        input.parentElement.classList.remove('error-invalid');
      } else if (input.value !== '' && input.value.match(/^[0-9]+$/) !== null) {
        input.parentElement.classList.remove('error-empty');
        input.parentElement.classList.add('error-invalid');
      } else {
        input.parentElement.classList.remove('error-empty');
        input.parentElement.classList.remove('error-invalid');
      }
    }
    
    const containsDateInput = function(input) {
      if (input.value === '') {
        input.parentElement.parentElement.classList.add('error-empty');
        input.parentElement.parentElement.classList.remove('error-invalid');
      } else if (input.value !== '' && input.value.match(/^[0-9]+$/) === null) { // wil return null if value has anything accept number
        input.parentElement.parentElement.classList.remove('error-empty');
        input.parentElement.parentElement.classList.add('error-invalid');
      } else {
        input.parentElement.parentElement.classList.remove('error-empty');
        input.parentElement.parentElement.classList.remove('error-invalid');
      }
    }
    
    const containsOtherInput = function(input) {
      if (input.value === '') {
        input.parentElement.classList.add('error-empty');
        input.parentElement.classList.remove('error-invalid');
      } else if (input.value !== '' && input.value.match(/^[0-9]+$/) === null) {
        input.parentElement.classList.remove('error-empty');
        input.parentElement.classList.add('error-invalid');
      } else {
        input.parentElement.classList.remove('error-empty');
        input.parentElement.classList.remove('error-invalid');
      }
    }
    
    modalClose.addEventListener('click', () => {
      modal.style.display = "none";
    })
    .input-field .error {
      color: red;
      font-size: .7rem;
      display: none;
    }
    
    .input-field.error-empty .empty {
      display: block;
    }
    
    .input-field.error-invalid .invalid {
      display: block;
    }
    
    .modal {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      display: none;
      background: white;
    }
    <form>
      <div class="input-field">
        <label for="name">Cardholder Name</label>
        <input type="text" placeholder="e.g. Jane Appleseed" id="name" name="name" maxlength="25" class="name-input">
        <p class="error empty">Can't be blank</p>
        <p class="error invalid">Wrong format, letters only</p>
      </div>
      <div class="input-field">
        <label for="number">Card Number</label>
        <input type="text" placeholder="e.g. 1234 5678 9123 0000" id="number" name="number" minlength="16" maxlength="16" class="number-input">
        <p class="error empty">Can't be blank</p>
        <p class="error invalid">Wrong format, numbers only</p>
      </div>
      <div class="flex-row">
        <div class="input-field date-container">
          <label id='date'>Exp. Date (MM/YY)</label>
          <div class="date-input">
            <input type='text' placeholder="MM" id='month' name="month" aria-labelledby='date' class="date month-input" maxlength="2" />
            <input type='text' placeholder="YY" id='year' name="year" aria-labelledby='date' class="date year-input" maxlength="2" />
          </div>
          <p class="error empty">Can't be blank</p>
          <p class="error invalid">Wrong format, numbers only</p>
        </div>
        <div class="input-field">
          <label for="cvc">CVC</label>
          <input type="text" placeholder="e.g. 123" id="cvc" name="cvc" minlength="3" maxlength="4" class="cvc-input">
          <p class="error empty">Can't be blank</p>
          <p class="error invalid">Wrong format, numbers only</p>
        </div>
      </div>
      <button type="submit" class="btn">Confirm</button>
    </form>
    <section class="modal">
      <img src="./images/icon-complete.svg" alt="">
      <h2>Thank you!</h2>
      <p>We've added your card details</p>
      <button type="button" class="btn close">Continue</button>
    </section>

    根据互联网资料,CVC 是 3 位或 4 位数字,因此添加了一个minlength="3"

    【讨论】:

      【解决方案2】:

      html 自己做所有的空白验证。我在每个输入标签上添加 required 属性

      const form = document.querySelector('form');
          const inputs = document.querySelectorAll('input');
          const modal = document.querySelector('.modal');
          const modalClose = document.querySelector('.close');
      
          form.addEventListener('submit', (e) => {
              e.preventDefault();
              inputs.forEach(input => {
                  if (input.classList.contains('name-input')) {
                      containsNameInput(input)
                  } else if (input.classList.contains('date')) {
                      containsDateInput(input)
                  } else {
                      containsOtherInput(input)
                  }
      
      
              })
          })
          inputs.forEach(input => {
              if (input.parentElement.classList.contains('error-empty')
                  || input.parentElement.classList.contains('error-invalid')
                  || input.parentElement.parentElement.classList.contains('error-invalid')
                  || input.parentElement.parentElement.classList.contains('error-empty')) {
                  modal.style.display = "block";
              } else {
                  modal.style.display = "none";
              }
      
          })
      
          const containsNameInput = function (input) {
              if (input.value === '') {
                  input.parentElement.classList.add('error-empty');
                  input.parentElement.classList.remove('error-invalid');
              } else if (input.value !== '' && input.value.match(/^[0-9]+$/) !== null) {
                  input.parentElement.classList.remove('error-empty');
                  input.parentElement.classList.add('error-invalid');
              }
              else {
                  input.parentElement.classList.remove('error-empty');
                  input.parentElement.classList.remove('error-invalid');
              }
          }
      
          const containsDateInput = function (input) {
              if (input.value === '') {
                  input.parentElement.parentElement.classList.add('error-empty');
                  input.parentElement.parentElement.classList.remove('error-invalid');
              } else if (input.value !== '' && input.value.match(/^[0-9]+$/) === null) {  // wil return null if value has anything accept number
                  input.parentElement.parentElement.classList.remove('error-empty');
                  input.parentElement.parentElement.classList.add('error-invalid');
              } else {
                  input.parentElement.parentElement.classList.remove('error-empty');
                  input.parentElement.parentElement.classList.remove('error-invalid');
              }
          }
      
          const containsOtherInput = function (input) {
              if (input.value === '') {
                  input.parentElement.classList.add('error-empty');
                  input.parentElement.classList.remove('error-invalid');
              } else if (input.value !== '' && input.value.match(/^[0-9]+$/) === null) {
                  input.parentElement.classList.remove('error-empty');
                  input.parentElement.classList.add('error-invalid');
              } else {
                  input.parentElement.classList.remove('error-empty');
                  input.parentElement.classList.remove('error-invalid');
              }
          }
      
      
          modalClose.addEventListener('click', () => {
              modal.style.display = "none";
          })
      .input-field .error{
          color: red;
          font-size: .7rem;
          display: none;
      }
      .input-field.error-empty .empty{
          display: block;
      }
      .input-field.error-invalid .invalid{
          display: block;
      }
      .modal{
          position: absolute;
          top: 0;
          left: 0;
          width: 100%;
          height: 100%;
          display: none;
          background:white;
      }
      <form>
              <div class="input-field">
                <label for="name">Cardholder Name</label>
                <input type="text" placeholder="e.g. Jane Appleseed" id="name" name="name" maxlength="25" class="name-input" >
                <p class="error empty">Can't be blank</p>
                <p class="error invalid">Wrong format, letters only</p>
              </div>
              <div class="input-field">
                <label for="number">Card Number</label>
                <input type="text" placeholder="e.g. 1234 5678 9123 0000" id="number" name="number" minlength="16" maxlength="16" class="number-input" >
                <p class="error empty">Can't be blank</p>
                <p class="error invalid">Wrong format, numbers only</p>
              </div>
              <div class="flex-row">
                <div class="input-field date-container">
                  <label id='date'>Exp. Date (MM/YY)</label>
                  <div class="date-input">
                    <input type='text' placeholder="MM" id='month' name="month" aria-labelledby='date' class="date month-input" maxlength="2" />
                    <input type='text' placeholder="YY" id='year' name="year" aria-labelledby='date' class="date year-input" maxlength="2"/>
                  </div>
                  <p class="error empty">Can't be blank</p>
                  <p class="error invalid">Wrong format, numbers only</p>
                </div>
                <div class="input-field">
                  <label for="cvc">CVC</label>
                  <input type="text" placeholder="e.g. 123" id="cvc" name="cvc" maxlength="4" class="cvc-input" >
                  <p class="error empty">Can't be blank</p>
                  <p class="error invalid">Wrong format, numbers only</p>
                </div>
              </div>
              <button type="submit" class="btn">Confirm</button>
            </form>
            <section class="modal">
              <img src="./images/icon-complete.svg" alt="">
              <h2>Thank you!</h2>
              <p>We've added your card details</p>
              <button type="button" class="btn close">Continue</button>
            </section>

      【讨论】:

      • 嗨,法鲁克!虽然这是一个很好的方法,但实际上我不想显示任何默认错误文本。我想用自定义文本来实现这一点。
      猜你喜欢
      • 2012-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-30
      • 2019-01-28
      • 1970-01-01
      • 2023-04-08
      • 1970-01-01
      相关资源
      最近更新 更多