uni-forms.vue 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. <template>
  2. <view class="uni-form">
  3. <form @submit.stop="submitForm" @reset="resetForm">
  4. <slot></slot>
  5. </form>
  6. </view>
  7. </template>
  8. <script>
  9. /**
  10. * Forms 自动校验的表单
  11. * @description 由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据
  12. * @tutorial https://ext.dcloud.net.cn/plugin?id=2773
  13. * @property {Object} formRules 表单校验规则
  14. * @property {String} trigger 校验触发器方式 默认 blur 可选 [blur|change|submit]
  15. * @property {String} labelPosition label 位置 默认 left 可选 [top|left]
  16. * @property {String|Number} labelWidth label 宽度,默认 65px
  17. * @property {String} labelAlign label 居中方式 默认 left 可选 [left|center|right]
  18. * @property {String} errorMessageType 错误提示类型 默认 bottom 可选 [none|top|bottom|toast|alert]
  19. */
  20. import Validator from './schema-validator.js'
  21. export default {
  22. name: 'uniForms',
  23. props: {
  24. // 表单校验规则
  25. formRules: {
  26. type: Object,
  27. default () {
  28. return {}
  29. }
  30. },
  31. // 校验触发器方式,默认 关闭
  32. trigger: {
  33. type: String,
  34. default: ''
  35. },
  36. // label 位置,可选值 top/left
  37. labelPosition: {
  38. type: String,
  39. default: 'left'
  40. },
  41. // label 宽度,单位 px
  42. labelWidth: {
  43. type: [String, Number],
  44. default: 65
  45. },
  46. // label 居中方式,可选值 left/center/right
  47. labelAlign: {
  48. type: String,
  49. default: 'left'
  50. },
  51. // 错误提示类型 可选值 none/ top / bottom /toast / alert
  52. errorMessageType: {
  53. type: String,
  54. default: 'bottom'
  55. }
  56. },
  57. provide() {
  58. return {
  59. form: this
  60. }
  61. },
  62. data() {
  63. return {
  64. rules: {},
  65. formData: {}
  66. };
  67. },
  68. watch: {
  69. formRules(newVal) {
  70. this.init(newVal)
  71. },
  72. trigger(trigger) {
  73. this.formTrigger = trigger
  74. }
  75. },
  76. created() {
  77. this.childrens = []
  78. this.init(this.formRules)
  79. },
  80. methods: {
  81. init(formRules) {
  82. if (Object.keys(formRules).length > 0) {
  83. this.formTrigger = this.trigger
  84. this.validator = new Validator(formRules)
  85. }
  86. },
  87. /**
  88. * 公开给用户使用
  89. * 设置自定义表单组件 value 值
  90. * @param {String} name 字段名称
  91. * @param {String} value 字段值
  92. */
  93. setValue(name, value, callback) {
  94. this.formData[name] = value
  95. let example = this.childrens.find(child => child.name === name)
  96. example.val = value
  97. return example.triggerCheck(value, callback)
  98. },
  99. /**
  100. * TODO 表单提交, 小程序暂不支持这种用法
  101. * @param {Object} event
  102. */
  103. submitForm(event) {
  104. const value = event.detail.value
  105. return this.validateAll(value || this.formData, 'submit')
  106. },
  107. /**
  108. * 表单重置
  109. * @param {Object} event
  110. */
  111. resetForm(event) {
  112. this.childrens.forEach(item => {
  113. item.errMsg = ''
  114. item.val = ''
  115. item.$emit('input', '')
  116. })
  117. this.$emit('reset', event)
  118. },
  119. /**
  120. * 触发表单校验,通过 @validate 获取
  121. * @param {Object} validate
  122. */
  123. validateCheck(validate) {
  124. if (validate === null) validate = null
  125. this.$emit('validate', validate)
  126. },
  127. /**
  128. * 校验所有或者部分表单
  129. */
  130. validateAll(invalidFields, type, callback) {
  131. if (!this.validator) {
  132. this.$emit('submit', {
  133. detail: {
  134. value: invalidFields,
  135. errors: null
  136. }
  137. })
  138. return
  139. }
  140. this.childrens.forEach(item => {
  141. item.errMsg = ''
  142. })
  143. let promise;
  144. // if no callback, return promise
  145. if (callback && typeof callback !== 'function' && Promise) {
  146. promise = new Promise((resolve, reject) => {
  147. callback = function(valid, invalidFields) {
  148. !valid ? resolve(invalidFields) : reject(valid);
  149. };
  150. });
  151. }
  152. let result = this.validator.invokeValidateUpdate(invalidFields, true)
  153. console.log('-=-=-', invalidFields, result);
  154. if (Array.isArray(result)) {
  155. if (result.length === 0) result = null
  156. }
  157. let example = null
  158. result && result.forEach(item => {
  159. example = this.childrens.find(child => child.name === item.key)
  160. if (example) example.errMsg = item.errorMessage
  161. })
  162. if (type === 'submit') {
  163. this.$emit('submit', {
  164. detail: {
  165. value: invalidFields,
  166. errors: result
  167. }
  168. })
  169. } else {
  170. this.$emit('validate', result)
  171. }
  172. callback && typeof callback === 'function' && callback(result ? false : true, result ? result : invalidFields)
  173. if (promise && callback) return promise
  174. },
  175. /**
  176. * 外部调用方法
  177. * 手动提交校验表单
  178. * 对整个表单进行校验的方法,参数为一个回调函数。
  179. */
  180. submit() {
  181. // let invalidFields = {}
  182. // this.childrens.forEach(item => {
  183. // item.parentVal((val) => {
  184. // invalidFields = Object.assign({}, invalidFields, val)
  185. // })
  186. // })
  187. return this.validateAll(this.formData, 'submit')
  188. },
  189. /**
  190. * 外部调用方法
  191. * 校验表单
  192. * 对整个表单进行校验的方法,参数为一个回调函数。
  193. */
  194. validate(callback) {
  195. return this.validateAll(this.formData, '', callback)
  196. },
  197. /**
  198. * 部分表单校验
  199. * @param {Object} props
  200. * @param {Object} cb
  201. */
  202. validateField(props, callback) {
  203. props = [].concat(props);
  204. let invalidFields = {}
  205. this.childrens.forEach(item => {
  206. // item.parentVal((val, name) => {
  207. if (props.indexOf(item.name) !== -1) {
  208. invalidFields = Object.assign({}, invalidFields, {
  209. [item.name]: this.formData[item.name]
  210. })
  211. }
  212. // })
  213. })
  214. console.log(invalidFields);
  215. return this.validateAll(invalidFields, '', callback)
  216. },
  217. /**
  218. * 对整个表单进行重置,将所有字段值重置为初始值并移除校验结果
  219. */
  220. resetFields() {
  221. this.resetForm()
  222. },
  223. /**
  224. * 移除表单项的校验结果。传入待移除的表单项的 prop 属性或者 prop 组成的数组,如不传则移除整个表单的校验结果
  225. */
  226. clearValidate(props) {
  227. props = [].concat(props);
  228. this.childrens.forEach(item => {
  229. if (props.length === 0) {
  230. item.errMsg = ''
  231. } else {
  232. if (props.indexOf(item.name) !== -1) {
  233. item.errMsg = ''
  234. }
  235. }
  236. })
  237. }
  238. }
  239. }
  240. </script>
  241. <style scoped></style>