验证规则绑定

avalon2砍掉了不少功能(如ms-include,ms-data),腾出空间加了其他更有用的功能。 数据验证就是其中之一。现在avalon2内置的验证指令是参考之前的oniui验证框架与jquery validation。

此指令只能用于添加ms-duplex指令的表单元素上。

avalon内置验证规则有

规则描述
required(true)必须输入的字段
norequired(true)不是必填的字段
email(true)必须输入正确格式的电子邮件
url(true)必须输入正确格式的网址
date(true或正则)必须输入正确格式的日期。默认是要求YYYY-MM-dd这样的格式
number(true)必须输入合法的数字(负数,小数)
digits(true)必须输入整数
pattern(正则或true)让输入数据匹配给定的正则,如果没有指定,那么会到元素上找pattern属性转换成正则再匹配
equalto(ID名)输入值必须和 #id 元素的value 相同
maxlength:5输入长度最多是 5 的字符串(汉字算一个字符)
minlength:10输入长度最小是 10 的字符串(汉字算一个字符)
chs(true)要求输入全部是中文
max:5输入值不能大于 5
min:10输入值不能小于 10

这些验证规则要求使用ms-rules指令表示,要求为一个普通的JS对象。

此外要求验征框架能动起来,还必须在所有表单元素外包一个form元素,在form元素上加ms-validate指令。

  1. var vm = avalon.define({
  2. $id: "validate1",
  3. aaa: "",
  4. bbb: '',
  5. ccc: '',
  6. validate: {
  7. onError: function (reasons) {
  8. reasons.forEach(function (reason) {
  9. console.log(reason.getMessage())
  10. })
  11. },
  12. onValidateAll: function (reasons) {
  13. if (reasons.length) {
  14. console.log('有表单没有通过')
  15. } else {
  16. console.log('全部通过')
  17. }
  18. }
  19. }
  20. })
  1. <div ms-controller="validate1">
  2. <form ms-validate="@validate">
  3. <p><input ms-duplex="@aaa" placeholder="username"
  4. ms-rules='{required:true,chs:true}' >{{@aaa}}</p>
  5. <p><input type="password" id="pw" placeholder="password"
  6. ms-rules='{required:true}'
  7. ms-duplex="@bbb" /></p>
  8. <p><input type="password"
  9. ms-rules="{required:true,equalto:'pw'}" placeholder="再填一次"
  10. ms-duplex="@ccc | change" /></p>
  11. <p><input type="submit" value="submit"/></p>
  12. </form>
  13. </div>

因此,要运行起avalon2的内置验证框架,必须同时使用三个指令。ms-validate用于定义各种回调与全局的配置项(如什么时候进行验证)。ms-duplex用于将单个表单元素及相关信息组成一个Field对象,放到ms-validater指令的fields数组中。ms-rules用于定义验证规则。如果验证规则不满足你,你可以自行在avalon.validators对象上添加。

现在我们可以一下ms-validate的用法。其对应一个对象。

配置项描述
fields框架自行添加,用户不用写。为一个数组,放置ms-duplex生成的Field对象。
onSuccess空函数,单个验证成功时触发,this指向被验证元素this指向被验证元素,传参为一个对象数组外加一个可能存在的事件对象。
onError空函数,单个验证失败时触发,this与传参情况同上
onComplete空函数,单个验证无论成功与否都触发,this与传参情况同上。
onValidateAll空函数,整体验证后或调用了validateAll方法后触发;有了这东西你就不需要在form元素上ms-on-submit="submitForm",直接将提交逻辑写在onValidateAll回调上
onReset空函数,表单元素获取焦点时触发,this指向被验证元素,大家可以在这里清理className、value
validateInBlurtrue,在blur事件中进行验证,触发onSuccess, onError, onComplete回调
validateInKeyuptrue, 在keyup事件中进行验证,触发onSuccess, onError, onComplete回调。当用户在ms-duplex中使用change debounce过滤器时会失效
validateAllInSubmittrue,在submit事件中执行onValidateAll回调
resetInFocustrue,在focus事件中执行onReset回调
deduplicateInValidateAllfalse,在validateAll回调中对reason数组根据元素节点进行去重

我们看一下如何自定义验证规则.

比如说我们有一个变态的需求,一个字段可以不填,但如果要填的话一定要是合法的数字,并且大于零.这就需要自定义规则了.

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>ms-validate</title>
  5. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  6. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  7. <script src="../dist/avalon.js"></script>
  8. <script>
  9. avalon.validators.aaa = {
  10. message: '必须数字并大于0',
  11. get: function (value, field, next) {
  12. //想知道它们三个参数是什么,可以console.log(value, field,next)
  13. var ok = (value === '' || (Number(value) > 0))
  14. next(ok)
  15. return value
  16. }
  17. }
  18. var vm = avalon.define({
  19. $id: "test",
  20. aaa: '',
  21. validate: {
  22. onError: function (reasons) {
  23. reasons.forEach(function (reason) {
  24. console.log(reason.getMessage())
  25. })
  26. },
  27. onValidateAll: function (reasons) {
  28. if (reasons.length) {
  29. console.log('有表单没有通过')
  30. } else {
  31. console.log('全部通过')
  32. }
  33. }
  34. }
  35. })
  36. </script>
  37. </head>
  38. <body ms-controller="test">
  39. <form class="cmxform" ms-validate="@validate" >
  40. <fieldset>
  41. <legend>自定义规则</legend>
  42. <p>
  43. <input
  44. ms-duplex="@aaa"
  45. ms-rules="{aaa: true}"
  46. >
  47. </p>
  48. </fieldset>
  49. <p>
  50. <input class="submit" type="submit" value="提交">
  51. </p>
  52. </fieldset>
  53. </form>
  54. </body>
  55. </html>

在上表还有一个没有提到的东西是如何显示错误信息,这个avalon不帮你处理。但提示信息会帮你拼好,如果你没有写,直接用验证规则的message,否则在元素上找data-message或data-required-message这样的属性。

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>ms-validate</title>
  5. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  6. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  7. <script src="../dist/avalon.js"></script>
  8. <script>
  9. var vm = avalon.define({
  10. $id: "test",
  11. rules:{required:true,email:true},
  12. email:'',
  13. validate: {
  14. onError: function (reasons) {
  15. reasons.forEach(function (reason) {
  16. console.log(reason.getMessage())
  17. })
  18. },
  19. onValidateAll: function (reasons) {
  20. if (reasons.length) {
  21. console.log('有表单没有通过')
  22. } else {
  23. console.log('全部通过')
  24. }
  25. }
  26. }
  27. })
  28. </script>
  29. </head>
  30. <body ms-controller="test">
  31. <form class="cmxform" ms-validate="@validate" >
  32. <fieldset>
  33. <legend>验证完整的表单</legend>
  34. <p>
  35. <label for="email">Email</label>
  36. <input id="email"
  37. name="email"
  38. type="email"
  39. ms-duplex="@email"
  40. ms-rules="@rules"
  41. data-required-message="请输入"
  42. data-email-message="请输入一个正确的邮箱"
  43. >
  44. </p>
  45. </fieldset>
  46. <p>
  47. <input class="submit" type="submit" value="提交">
  48. </p>
  49. </fieldset>
  50. </form>
  51. </body>
  52. </html>

最后给一个复杂的例子:

  1. <script>
  2. var vm = avalon.define({
  3. $id: "validate2",
  4. firstname: '司徒正美',
  5. lastname: '',
  6. username: '',
  7. password: '',
  8. confirm_password: '',
  9. email: '',
  10. agree: false,
  11. topic: [],
  12. toggle: false,
  13. validate: {
  14. onError: function (reasons) {
  15. reasons.forEach(function (reason) {
  16. console.log(reason.getMessage())
  17. })
  18. },
  19. onValidateAll: function (reasons) {
  20. if (reasons.length) {
  21. console.log('有表单没有通过')
  22. } else {
  23. console.log('全部通过')
  24. }
  25. }
  26. }
  27. })
  28. avalon.validators.checked = {
  29. message: '必须扣上',
  30. get: function (value, field, next) {
  31. next(value)
  32. return value
  33. }
  34. }
  35. avalon.validators.selecttwo = {
  36. message: '至少选择两个',
  37. get: function (value, field, next) {
  38. next(!vm.toggle || value.length >= 2)
  39. return value
  40. }
  41. }
  42. </script>
  43. <div ms-controller="validate2">
  44. <form class="cmxform" ms-validate="@validate" >
  45. <fieldset>
  46. <legend>验证完整的表单</legend>
  47. <p>
  48. <label for="firstname">名字</label>
  49. <input id="firstname"
  50. name="firstname"
  51. ms-duplex="@firstname"
  52. ms-rules="{required:true, pattern: /[\u4e00-\u9fa5a-z]{2-8}/i }"
  53. data-required-message="必须是中文或字母(3-8个字符)" >
  54. </p>
  55. <p>
  56. <label for="lastname">姓氏</label>
  57. <input id="lastname"
  58. name="lastname"
  59. ms-duplex="@lastname"
  60. ms-rules="{required:true}"
  61. data-required-message="请输入您的姓氏"
  62. >
  63. </p>
  64. <p>
  65. <label for="username">用户名</label>
  66. <input id="username"
  67. name="username"
  68. ms-duplex="@username | change"
  69. ms-rules="{required:true, minlength:2}"
  70. >
  71. </p>
  72. <p>
  73. <label for="password">密码</label>
  74. <input id="password"
  75. name="password"
  76. type="password"
  77. ms-duplex="@password"
  78. ms-rules="{required:true,minlength:5}"
  79. data-required-message="请输入密码"
  80. data-required-message="密码长度不能小于 5 个字母"
  81. >
  82. </p>
  83. <p>
  84. <label for="confirm_password">验证密码</label>
  85. <input id="confirm_password"
  86. name="confirm_password"
  87. type="password"
  88. ms-duplex="@confirm_password | change"
  89. ms-rules="{required:true,equalto:'password'}"
  90. data-equalto-message="两次密码输入不一致"
  91. >
  92. </p>
  93. <p>
  94. <label for="email">Email</label>
  95. <input id="email"
  96. name="email"
  97. type="email"
  98. ms-duplex="@email"
  99. ms-rules="{email:true}"
  100. data-email-message="请输入一个正确的邮箱"
  101. >
  102. </p>
  103. <p>
  104. <label for="agree">请同意我们的声明</label>
  105. <input type="checkbox" class="checkbox" id="agree" name="agree"
  106. ms-duplex-checked="@agree"
  107. ms-rules="{checked:true}"
  108. >
  109. </p>
  110. <p>
  111. <label for="newsletter">我乐意接收新信息</label>
  112. <input type="checkbox" class="checkbox"
  113. id="newsletter"
  114. name="newsletter"
  115. ms-duplex-checked="@toggle"
  116. >
  117. </p>
  118. <fieldset id="newsletter_topics" ms-visible="@toggle" >
  119. <legend>主题 (至少选择两个) </legend>
  120. <label for="topic_marketflash">
  121. <input type="checkbox"
  122. id="topic_marketflash"
  123. value="marketflash"
  124. name="topic[]"
  125. ms-duplex="@topic"
  126. ms-rules="{selecttwo:true}"
  127. >Marketflash
  128. </label>
  129. <label for="topic_fuzz">
  130. <input type="checkbox"
  131. id="topic_fuzz"
  132. value="fuzz"
  133. name="topic[]"
  134. ms-duplex="@topic"
  135. ms-rules="{selecttwo:true}"
  136. >Latest fuzz
  137. </label>
  138. <label for="topic_digester">
  139. <input type="checkbox"
  140. id="topic_digester"
  141. value="digester"
  142. name="topic[]"
  143. ms-duplex="@topic"
  144. ms-rules="{selecttwo:true}"
  145. >Mailing list digester
  146. </label>
  147. <label for="topic" class="error" style="display:none">至少选择两个</label>
  148. </fieldset>
  149. <p>
  150. <input class="submit" type="submit" value="提交">
  151. </p>
  152. </fieldset>
  153. </form>
  154. </div>