Form Validator


基于 HTML5 的表单验证,使用 H5 typerequiredpatternminmaxminlengthmaxlength 等属性进行验证,在不支持 JS 的环境中可以平稳退化到 H5 原生验证。

使用示例

HTML5 原生表单验证

如果表单只面向 H5 浏览器,而且不需要过多的控制,那原生的表单验证无疑是省时省力的选择,通过 :valid:invalid 伪类可以控制不同验证状态的样式。

H5 原生表单验证
<form action="" class="am-form">
  <fieldset>
    <legend>H5 原生表单验证</legend>
    <div class="am-form-group">
      <label for="doc-vld-name">用户名:</label>
      <input type="text" id="doc-vld-name" minlength="3" placeholder="输入用户名" class="am-form-field" required/>
    </div>
  </fieldset>
</form>

参考链接:

JS 表单验证

JS 表单验证基于 HTML5 的各项验证属性进行:

注意:

HTML5 原生表单验证中 pattern 只验证值的合法性,也就是可以不填,如果填写则必须符合规则。如果是必填项,仍要添加 required 属性。该插件与 HTML5 的规则保持一致。

<!-- 下面三种写法等效 -->
<!-- 只内置了 email url number 三种类型的正则,可自行扩展 -->
<input type="email"/>

<!-- js-pattern-xx 其中 xx 为 pattern 库中的 key -->
<input type="text" class="js-pattern-email"/>

<input type="text" pattern="^(...email regex...)$"/>
JS 表单验证
<form action="" class="am-form" data-am-validator>
  <fieldset>
    <legend>JS 表单验证</legend>
    <div class="am-form-group">
      <label for="doc-vld-name-2">用户名:</label>
      <input type="text" id="doc-vld-name-2" minlength="3" placeholder="输入用户名(至少 3 个字符)" required/>
    </div>

    <div class="am-form-group">
      <label for="doc-vld-email-2">邮箱:</label>
      <input type="email" id="doc-vld-email-2" placeholder="输入邮箱" required/>
    </div>

    <div class="am-form-group">
      <label for="doc-vld-url-2">网址:</label>
      <input type="url" id="doc-vld-url-2" placeholder="输入网址" required/>
    </div>

    <div class="am-form-group">
      <label for="doc-vld-age-2">年龄:</label>
      <input type="number" class=""  id="doc-vld-age-2" placeholder="输入年龄  18-120" min="18" max="120" required />
    </div>

    <div class="am-form-group">
      <label class="am-form-label">爱好:</label>
      <label class="am-checkbox-inline">
        <input type="checkbox" value="橘子" name="docVlCb" minchecked="2" maxchecked="4" required> 橘子
      </label>
      <label class="am-checkbox-inline">
        <input type="checkbox" value="苹果" name="docVlCb"> 苹果
      </label>
      <label class="am-checkbox-inline">
        <input type="checkbox" value="菠萝" name="docVlCb"> 菠萝
      </label>
      <label class="am-checkbox-inline">
        <input type="checkbox" value="芒果" name="docVlCb"> 芒果
      </label>
      <label class="am-checkbox-inline">
        <input type="checkbox" value="香蕉" name="docVlCb"> 香蕉
      </label>
    </div>

    <div class="am-form-group">
      <label>性别: </label>
      <label class="am-radio-inline">
        <input type="radio"  value="" name="docVlGender" required></label>
      <label class="am-radio-inline">
        <input type="radio" name="docVlGender"></label>
      <label class="am-radio-inline">
        <input type="radio" name="docVlGender"> 其他
      </label>
    </div>

    <div class="am-form-group">
      <label for="doc-select-1">下拉单选框</label>
      <select id="doc-select-1" required>
        <option value="option1">选项一...</option>
        <option value="option2">选项二.....</option>
        <option value="option3">选项三........</option>
      </select>
      <span class="am-form-caret"></span>
    </div>

    <div class="am-form-group">
      <label for="doc-select-2">多选框</label>
      <select multiple class="" id="doc-select-2" minchecked="2" maxchecked="4">
        <option>1</option>
        <option>2</option>
        <option>3</option>
        <option>4</option>
        <option>5</option>
      </select>
    </div>

    <div class="am-form-group">
      <label for="doc-vld-ta-2">评论:</label>
      <textarea id="doc-vld-ta-2" minlength="10" maxlength="100"></textarea>
    </div>

    <button class="am-btn am-btn-secondary" type="submit">提交</button>
  </fieldset>
</form>

等值验证

通过 data-equal-to 指定要比较的域。

密码验证
<form action="" class="am-form" data-am-validator>
  <fieldset>
    <legend>密码验证</legend>
    <div class="am-form-group">
      <label for="doc-vld-name-2">用户名:</label>
      <input type="text" id="doc-vld-name-2" minlength="3"
             placeholder="输入用户名(至少 3 个字符)" required/>
    </div>

    <div class="am-form-group">
      <label for="doc-vld-pwd-1">密码:</label>
      <input type="password" id="doc-vld-pwd-1" placeholder="6 位数字的银行卡密码" pattern="^\d{6}$" required/>
    </div>

    <div class="am-form-group">
      <label for="doc-vld-pwd-2">确认密码:</label>
      <input type="password" id="doc-vld-pwd-2" placeholder="请与上面输入的值一致" data-equal-to="#doc-vld-pwd-1" required/>
    </div>

    <button class="am-btn am-btn-secondary" type="submit">提交</button>
  </fieldset>
</form>

自定义验证

插件预置的功能不可能满足各异的需求,通过 validate 选项,可以自定义验证规则,如远程验证等。

$('#your-form').validator({
  validate: function(validity) {
    // 在这里编写你的验证逻辑
  }

参数 validity 是一个类似 H5 ValidityState 属性的对象。只要中主要用到的包括:

其它属性用来描述验证出错的细节,包括:

{
  customError: false,
  patternMismatch: false,
  rangeOverflow: false, // higher than maximum
  rangeUnderflow: false, // lower than  minimum
  stepMismatch: false,
  tooLong: false,
  // value is not in the correct syntax
  typeMismatch: false,
  // Returns true if the element has no value but is a required field
  valueMissing: false
}

H5 浏览器原生验证通过错误细节来显示提示信息,插件中暂未使用到这些属性,如果实在不想写,可以略过。

需要注意的注意细节:

return $.ajax({
    url: '...',
    // cache: false, 实际使用中请禁用缓存
    dataType: 'json'
  }).then(function(data) {
    // Ajax 请求成功,根据服务器返回的信息,设置 validity.valid = true or flase

    // 返回 validity
    return validity;
  }, function() {
    // Ajax 请求失败,根据需要决定验证是否通过,然后返回 validity
    return validity;
  });
自定义验证
<form action="" class="am-form" id="doc-vld-ajax">
  <fieldset>
    <legend>自定义验证</legend>
    <div class="am-form-group">
      <label for="doc-vld-ajax-count">Ajax 服务器端验证:</label>
      <input type="text" class="js-ajax-validate" id="doc-vld-ajax-count"
             placeholder="只能填写数字 10" data-validate-async/>
    </div>

    <div class="am-form-group">
      <label for="doc-vld-sync">客户端验证:</label>
      <input type="text" class="js-sync-validate" id="doc-vld-sync"
             placeholder="只能填写数字 10"/>
    </div>

    <button class="am-btn am-btn-secondary" type="submit">提交</button>
  </fieldset>
</form>
$(function() {
  $('#doc-vld-ajax').validator({
    validate: function(validity) {
      var v = $(validity.field).val();

      var comparer = function(v1, v2) {
        if (v1 != v2) {
          validity.valid = false;
        }

        // 这些属性目前没什么用,如果不想写可以忽略
        if (v2 < 10) {
          validity.rangeUnderflow = true;
        } else if(v2 > 10) {
          validity.rangeOverflow = true;
        }
      };

      // Ajax 验证
      if ($(validity.field).is('.js-ajax-validate')) {
        // 异步操作必须返回 Deferred 对象
        return $.ajax({
          url: 'http://7jpqbr.com1.z0.glb.clouddn.com/validate.json',
          // cache: false, 实际使用中请禁用缓存
          dataType: 'json'
        }).then(function(data) {
          comparer(data.count, v);
          return validity;
        }, function() {
          return validity;
        });
      }

      // 本地验证,同步操作,无需返回值
      if ($(validity.field).is('.js-sync-validate')) {
        comparer(10, v);
        // return validity;
      }
    }
  });
});

使用方式

通过 Data API

form 上添加 data-am-validator 属性(同时可以设置相关选项)。

通过 JS

$(function() {
  $('#your-form').validator(options);
});

参数说明

{
  // 是否使用 H5 原生表单验证,不支持浏览器会自动退化到 JS 验证
  H5validation: false,

  // 内置规则的 H5 input type,这些 type 无需添加 pattern
  H5inputType: ['email', 'url', 'number'],

  // 验证正则
  // key1: /^...$/,包含 `js-pattern-key1` 的域会自动应用改正则
  patterns: {},

  // 规则 class 钩子前缀
  patternClassPrefix: 'js-pattern-',

  activeClass: 'am-active',

  // 验证不通过时添加到域上的 class
  inValidClass: 'am-field-error',

  // 验证通过时添加到域上的 class
  validClass: 'am-field-valid',

  // 表单提交的时候验证
  validateOnSubmit: true,

  // 表单提交时验证的域
  // Elements to validate with allValid (only validating visible elements)
  // :input: selects all input, textarea, select and button elements.
  allFields: ':input:visible:not(:button, :disabled, .am-novalidate)',

  // 调用 validate() 方法的自定义事件
  customEvents: 'validate',

  // 下列元素触发以下事件时会调用验证程序
  keyboardFields: ':input:not(:button, :disabled,.am-novalidate)',
  keyboardEvents: 'focusout, change', // keyup, focusin

  activeKeyup: true,

  // 鼠标点击下列元素时会调用验证程序
  pointerFields: 'input[type="range"]:not(:disabled, .am-novalidate), ' +
  'input[type="radio"]:not(:disabled, .am-novalidate), ' +
  'input[type="checkbox"]:not(:disabled, .am-novalidate), ' +
  'select:not(:disabled, .am-novalidate), ' +
  'option:not(:disabled, .am-novalidate)',
  pointerEvents: 'click',

  // 域通过验证时回调
  onValid: function(validity) {
  },

  // 验证出错时的回调, validity 对象包含相关信息,格式通 H5 表单元素的 validity 属性
  onInValid: function(validity) {
  },

  // 域验证通过时添加的操作,通过该接口可定义各种验证提示
  markValid: function(validity) {
    // this is Validator instance
    var options = this.options;
    var $field  = $(validity.field);
    var $parent = $field.closest('.am-form-group');
    $field.addClass(options.validClass).
      removeClass(options.inValidClass);

    $parent.addClass('am-form-success').removeClass('am-form-error');

    options.onValid.call(this, validity);
  },

  // 域验证失败时添加的操作,通过该接口可定义各种验证提示
  markInValid: function(validity) {
    var options = this.options;
    var $field  = $(validity.field);
    var $parent = $field.closest('.am-form-group');
    $field.addClass(options.inValidClass + ' ' + options.activeClass).
      removeClass(options.validClass);

    $parent.addClass('am-form-error').removeClass('am-form-success');

    options.onInValid.call(this, validity);
  },

  // 自定义验证程序接口,详见示例
  validate: function(validity) {
    // return validity;
  },

  // 定义表单提交处理程序
  //   - 如果没有定义且 `validateOnSubmit` 为 `true` 时,提交时会验证整个表单
  //   - 如果定义了表单提交处理程序,`validateOnSubmit` 将会失效
  //        function(e) {
  //          // 通过 this.isFormValid() 获取表单验证状态
  //          // Do something...
  //        }
  submit: null
}

扩展正则库

在 DOM Ready 之前执行以下操作:

(function($) {
  if ($.AMUI && $.AMUI.validator) {
    // 增加多个正则
    $.AMUI.validator.patterns = $.extend($.AMUI.validator.patterns, {
      colorHex: /^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/
    });
    // 增加单个正则
    $.AMUI.validator.patterns.yourpattern = /^your$/;
  }
})(window.jQuery);
<form action="" class="am-form" data-am-validator>
  <div class="am-form-group">
    <label for="">输入一个颜色值</label>
    <input type="text" class="js-pattern-colorHex" placeholder="如果填写,必须是 #xxx 或 #xxxxxx"/>
  </div>
  <div class="am-form-group">
    <label for="">your pattern</label>
    <input type="text" class="js-pattern-yourpattern" placeholder="必填,且只能填 your" required/>
  </div>
  <div>
    <button class="am-btn am-btn-secondary">提交</button>
  </div>
</form>

参考资源

常用正则表达式

注意事项

参考链接