首页 > 解决方案 > 使用 querySelectorAll 验证表单时 - 如何选择适当的跨度来输出错误

问题描述

我正在将事件侦听器添加到input字段中,querySelectorAll并且我想知道在发生表单“错误”时如何在适当的范围内显示错误消息。

我找到了这篇文章,看起来很有希望,但我不知道我目前的方法是否可行。

const inputs = document.querySelectorAll("input");
inputs.forEach(function(input){
    input.addEventListener("blur", function (){
        if(input.validity.valueMissing){
            //select appropriate span
        }
    })
})
<input type="text" id="surname" name="surname" required placeholder="Please enter your Surname" pattern="[A-Za-z]{2,15}" />
</br>
<span class="error" id="e_surname"></span>
</br>

不相关-此外,我想为电子邮件/电话/等输入字段显示不同的错误消息...我不知道我是否可以将所有这些都集中在一个“功能”中。

标签: javascript

解决方案


由于您的.error跨度以字段名称id为前缀"e_",因此您可以使用以下方法查找它:

document.querySelector(`#e_${input.getAttribute('name')}`)

我还会用^(line start) 和$(line end):包装你的模式^[A-Za-z]{2,15}$,因为没有你可以允许名称超过 15 个字符。

如果您希望 this 是隐式的,则可以在RegExp构造函数调用中添加它们:

pattern: input =>
  (pattern =>
    pattern ? new RegExp(`^{pattern}$`).test(input.value) : true)
  (input.getAttribute('pattern'))

例子

const VALIDATION_RULES = {
  required: input =>
    (required =>
      required || (required && input.value.length > 0))
    (input.hasAttribute('required')),
  pattern: input =>
    (pattern =>
      pattern ? new RegExp(pattern).test(input.value) : true)
    (input.getAttribute('pattern'))
};

const validateRules = (input, rules) =>
  rules.reduce((acc, rule) => acc && VALIDATION_RULES[rule](input), true);

const onInputBlur = e => {
  const
    input = e.target,
    valid = validateRules(input, [ 'required', 'pattern' ]);
  document.querySelector(`#e_${input.getAttribute('name')}`)
    .classList.toggle('show', !valid);
}

const inputs = document.querySelectorAll('input').forEach(input =>
  input.addEventListener('blur', onInputBlur));
.error { display: none; color: red; font-size: smaller; }
.error.show { display: block; }
<input type="text" id="surname" name="surname" required
  placeholder="Please enter your Surname"
  pattern="^[A-Za-z]{2,15}$" />
<br/>
<span class="error" id="e_surname">Please enter a valid value</span>
<br/>

处理此问题的更好方法是将错误与输入分组。这样,对于任何给定的输入,您可以上到包装器并返回到错误。

您甚至可以创建一个具有默认规则并接受新规则的规则验证类。每个规则都有一个detectandisValid函数。

class RuleValidator {
  constructor(rules) {
    this.rules = {  ...RuleValidator.defaultRules, ...rules };
  }
  validate (input) {
    return Object.values(this.rules)
      .filter(({ detect }) => detect(input))
      .reduce((acc, { isValid }) => acc && isValid(input), true);
  } 
}

RuleValidator.defaultRules = {
  required: {
    detect: input => input.hasAttribute('required'),
    isValid: input => input.value.length > 0
  },
  pattern: {
    detect: input => input.hasAttribute('pattern'),
    isValid: input => new RegExp(input.getAttribute('pattern')).test(input.value)
  }
};

const
  validator = new RuleValidator(),
  onInputBlur = e => {
    const
      input = e.target,
      field = input.closest('.field'),
      valid = validator.validate(input);
    field.querySelector('.error').classList.toggle('show', !valid);
  };

document.querySelectorAll('input').forEach(input =>
  input.addEventListener('blur', onInputBlur));
.field > label { font-weight: bold; }
.field > .error { display: none; color: red; font-size: smaller; }
.field > .error.show { display: block; }
<div class="field">
  <label>Surname</label>
  <input type="text" id="surname" name="surname" required
    placeholder="Please enter your Surname"
    pattern="^[A-Za-z]{2,15}$" />
  <span class="error" id="e_surname">Please enter a valid value</span>
</div>


推荐阅读