如果未经过验证,则停止提交表单

时间:2018-04-06 11:47:46

标签: javascript

我有一个有重量的表格,我确保每个重量都是:

  1. 一个数字
  2. 每个重量> 0
  3. 所有重量的总和= 100。
  4. 以下示例仅测试1和3:

    function assertWeightValidity() {
    
               let weightSum = 0;
    
               $.each($('[name^=weight_]'), function()
               {
                        chai.assert(isNaN(this.value) === false, 'Weights should be numbers!');
                        let currWeight = Number(this.value);
                        console.log(currWeight);
                        weightSum += currWeight;
                        <!-- assert nothing is zero -->
               });
               console.log(weightSum);
     }
    
    onEnterCalculate("#calculate", assertWeightValidity);
    

    然后我将onEnterCalculate函数定义为:

    function onEnterCalculate(selector, assertion) {
    
        middleware = assertion || null;
    
        document.onkeydown = function (evt) {
            var keyCode = evt ? (evt.which ? evt.which : evt.keyCode) : event.keyCode;
            if (keyCode == 13) {
                if(middleware) { middleware(); }
                $(selector).click();
            }
        }
    }
    

    我是JavaScript的新手。我用谷歌搜索,但我找不到解决方案。我想要实现的是,如果chai在任何时候抛出错误,我不想提交表单,我想提醒用户并让他们修改他们已经在表单中输入的内容。我发现通过preventDefault()调用可以实现类似的功能。不确定如何抓取assertWeightValidity()内的事件(因为我猜需要在chai抛出错误时生成事件)。目前发生的事情是,如果重量不好,chai会抛出一个Uncaught Exception,例如'sadasda',但无论如何它都会出现并发布表格。

    由于

2 个答案:

答案 0 :(得分:3)

简而言之,您可以在form submit个事件中运行验证。如果您在该功能中致电e.preventDefault()和/或return false,则不会提交。否则,它会。

document.querySelector('form').addEventListener('submit', e => {
  console.log('preventing submit');
  e.preventDefault();
});
<form action="#">
  <button type="submit">Submit</button>
</form>

从那里开始,只需验证您想要的代码,然后根据需要调用(或不调用)preventDefault()

document.querySelector('form').addEventListener('submit', e => {  
  if (!document.querySelector('input').value) {
    console.log('Must add a value');
    e.preventDefault();
  }
});
<form action="#">
  <label>Value: <input /></label>
  <button type="submit">Submit</button>
</form>

如果你有多个验证函数都返回一个布尔值(或者更好的是,一个错误消息),一个简单的检查方法是将它们放在一个数组中,然后使用every()或{{1}看看他们是否都很好。

filter()
const checkField = id => !!document.querySelector(`#${id}`).value;

document.querySelector('form').addEventListener('submit', e => {
  if (![checkField('a'), checkField('b'), checkField('c')].every(Boolean)) {
    console.log('All fields must have a value');
    e.preventDefault();
  }
});

更好的是,它可以返回错误消息,如果没有,那么您可以使用<form action="#"> <label>Value: <input id="a"/></label> <label>Value: <input id="b"/></label> <label>Value: <input id="c"/></label> <button type="submit">Submit</button> </form>收集错误消息:

filter()
const checkField = id => document.querySelector(`#${id}`).value ? undefined : `Field "${id}" must have a value`;

document.querySelector('form').addEventListener('submit', e => {
  const errors = [checkField('a'), checkField('b'), checkField('c')].filter(Boolean);
  
  if (errors.length) {
    console.log(errors);
    e.preventDefault();
  }
});

最后,由于您提到了抛出错误,如果您希望它实际抛出错误,您可以尝试捕获它们然后输出它们。

<form action="#">
  <label>Value: <input id="a"/></label>
  <label>Value: <input id="b"/></label>
  <label>Value: <input id="c"/></label>
  <button type="submit">Submit</button>
</form>
const checkField = id => {
  if (!document.querySelector(`#${id}`).value) {
    throw new Error(`Field ${id} must have a value`);
  }
};

document.querySelector('form').addEventListener('submit', e => {
  try {
    checkField('a');
    checkField('b');
    checkField('c');
  } catch (ex) {
    console.log(ex.message);
    e.preventDefault();
  }
});

这样做的缺点是你不能同时检查多个东西,因为它会在第一个错误时中止。

答案 1 :(得分:1)

您想要的不是听取键盘事件,而应该只检查表单触发的submit事件。它是一个非常方便的捕获所有,因为任何触发表单提交的用户交互(可以是回车键,单击提交按钮,或任何其他)将被此处理程序捕获。

由于您未使用&#34; jQuery&#34;标记您的问题而且您似乎熟悉ES6语法,我使用以下假设制定了我的答案。要获得您想要的结果,这很简单:

  1. 收听表格submit活动
  2. 重构您的assertWeightValidity()方法,以便抛出错误,我们可以在提交事件处理程序中捕获该错误
  3. assertWeightValidity()
  4. 中致电try
  5. 如果没有抛出错误,我们可以提交表单:)
  6. assertWeightValidity()方法的更多细节:您需要(1)首先检查权重输入元素是否具有可以解析为数字的非空值,以及(2)您还要检查总和如果它们匹配100,则为这些值。

    1. 使用Array.map()遍历所有输入元素并检索其值。在返回之前,您已经可以实现逻辑来检查它们是否是数字。返回时,请务必使用+运算符将值强制转换为数字(HTML值始终以字符串形式返回!)
    2. 使用Array.reduce()来总结您拥有的权重数组
    3. 检查金额是否与100匹配。
    4. 概念验证示例如下。测试用例:

      • 将任何字段留空。应抛出错误,因为一个或多个字段无法转换为数字
      • 在所有4个输入字段中使用1234。应该抛出错误,因为它们不能总和为100
      • 对每个字段使用25,总计为100,您应该会看到一个控制台日志,通知您该表单有效并将提交。

      请注意,由于我不知道chai的含义,我只是简单地评论了这一行:

      &#13;
      &#13;
      const customForm = document.getElementById('customForm');
      customForm.addEventListener('submit', function(e) {
      
        // Intercept default form submission
        e.preventDefault();
      
        // Assert weight validity
        try {
          assertWeightValidity.call(this)
        } catch (error) {
          console.warn(error);
          return;
        }
      
        // Programmatically trigger form submission if no errors are thrown
        console.log('Submitting form now');
        // Uncomment the next line to actually submit the form
        // this.submit();
      });
      
      // Returns if the weights are valid or not
      function assertWeightValidity() {
      
        // Get array of all weights
        const weightElements = Array.prototype.slice.call(this.querySelectorAll('input[name^=weight_]'));
      
        // Use `Array.map` to check if numbers can be parsed and return an array of weights
        const weightsArray = weightElements.map((weightElement) => {
          // If weight is empty or not a number, we throw an error and exit
          // chai.assert(!isNaN(weight.value), 'Weights should be numbers!');
          if (weightElement.value === '' || isNaN(weightElement.value))
            throw 'Weights should be numbers';
            
          // Otherwise, we return the value
          return +weightElement.value;
          
        });
        
        // Use `Array.reduce` to get the sum of weights
        const totalWeight = weightsArray.reduce((weight, accumulatedWeight) => weight + accumulatedWeight);
      
        if (totalWeight !== 100)
          throw 'Weights do not add up to 100';
      }
      &#13;
      input {
        display: block;
      }
      &#13;
      <form id="customForm">
        <input type="number" name="weight_1" placeholder="Enter a value for weight 1" />
        <input type="number" name="weight_2" placeholder="Enter a value for weight 2" />
        <input type="number" name="weight_3" placeholder="Enter a value for weight 3" />
        <input type="number" name="weight_4" placeholder="Enter a value for weight 4" />
        <button id="calculate">Calculate</button>
      </form>
      &#13;
      &#13;
      &#13;