refactor: form
							parent
							
								
									97aeaf74b4
								
							
						
					
					
						commit
						130982a037
					
				| 
						 | 
				
			
			@ -7,6 +7,7 @@ import warning from '../_util/warning';
 | 
			
		|||
import FormItem from './FormItem';
 | 
			
		||||
import { initDefaultProps, getListeners, getSlot } from '../_util/props-util';
 | 
			
		||||
import { ConfigConsumerProps } from '../config-provider';
 | 
			
		||||
import { getParams } from './utils';
 | 
			
		||||
 | 
			
		||||
export const FormProps = {
 | 
			
		||||
  layout: PropTypes.oneOf(['horizontal', 'inline', 'vertical']),
 | 
			
		||||
| 
						 | 
				
			
			@ -45,6 +46,8 @@ export const ValidationRule = {
 | 
			
		|||
  transform: PropTypes.func,
 | 
			
		||||
  /** custom validate function (Note: callback must be called) */
 | 
			
		||||
  validator: PropTypes.func,
 | 
			
		||||
  // 提交失败自动滚动到第一个错误字段
 | 
			
		||||
  scrollToFirstError: PropTypes.bool,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const Form = {
 | 
			
		||||
| 
						 | 
				
			
			@ -96,12 +99,17 @@ const Form = {
 | 
			
		|||
        this.$emit('submit', e);
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    resetFields() {
 | 
			
		||||
    resetFields(props = this.fields) {
 | 
			
		||||
      if (!this.model) {
 | 
			
		||||
        warning(false, 'FormModel', 'model is required for resetFields to work.');
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      this.fields.forEach(field => {
 | 
			
		||||
      const fields = props.length
 | 
			
		||||
        ? typeof props === 'string'
 | 
			
		||||
          ? this.fields.filter(field => props === field.prop)
 | 
			
		||||
          : this.fields.filter(field => props.indexOf(field.prop) > -1)
 | 
			
		||||
        : this.fields;
 | 
			
		||||
      fields.forEach(field => {
 | 
			
		||||
        field.resetField();
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
| 
						 | 
				
			
			@ -151,17 +159,81 @@ const Form = {
 | 
			
		|||
        return promise;
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    validateField(props, cb) {
 | 
			
		||||
      props = [].concat(props);
 | 
			
		||||
      const fields = this.fields.filter(field => props.indexOf(field.prop) !== -1);
 | 
			
		||||
      if (!fields.length) {
 | 
			
		||||
        warning(false, 'FormModel', 'please pass correct props!');
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      fields.forEach(field => {
 | 
			
		||||
        field.validate('', cb);
 | 
			
		||||
    scrollToField() {},
 | 
			
		||||
    getFieldsValue(allFields) {
 | 
			
		||||
      return allFields.map(({ prop, fieldValue }) => {
 | 
			
		||||
        return { [prop]: fieldValue };
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    validateFields() {
 | 
			
		||||
      this.validateField(...arguments);
 | 
			
		||||
    },
 | 
			
		||||
    validateField(ns, opt, cb) {
 | 
			
		||||
      const pending = new Promise((resolve, reject) => {
 | 
			
		||||
        const params = getParams(ns, opt, cb);
 | 
			
		||||
        const { names, options } = params;
 | 
			
		||||
        let { callback } = params;
 | 
			
		||||
        if (!callback || typeof callback === 'function') {
 | 
			
		||||
          const oldCb = callback;
 | 
			
		||||
          callback = (errors, values) => {
 | 
			
		||||
            if (oldCb) {
 | 
			
		||||
              oldCb(errors, values);
 | 
			
		||||
            } else if (errors) {
 | 
			
		||||
              reject({ errors, values });
 | 
			
		||||
            } else {
 | 
			
		||||
              resolve(values);
 | 
			
		||||
            }
 | 
			
		||||
          };
 | 
			
		||||
        }
 | 
			
		||||
        const allFields = names
 | 
			
		||||
          ? this.fields.filter(field => names.indexOf(field.prop) !== -1)
 | 
			
		||||
          : this.fields;
 | 
			
		||||
        const fields = allFields.filter(field => {
 | 
			
		||||
          const rules = field.getFilteredRule('');
 | 
			
		||||
          return rules && rules.length;
 | 
			
		||||
        });
 | 
			
		||||
        if (!fields.length) {
 | 
			
		||||
          callback(null, this.getFieldsValue(allFields));
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        if (!('firstFields' in options)) {
 | 
			
		||||
          options.firstFields = allFields.filter(field => {
 | 
			
		||||
            return !!field.validateFirst;
 | 
			
		||||
          });
 | 
			
		||||
        }
 | 
			
		||||
        let invalidFields = {};
 | 
			
		||||
        let valid = true;
 | 
			
		||||
        let count = 0;
 | 
			
		||||
        fields.forEach(field => {
 | 
			
		||||
          field.validate('', (message, field) => {
 | 
			
		||||
            if (message) {
 | 
			
		||||
              valid = false;
 | 
			
		||||
            }
 | 
			
		||||
            // TODO:
 | 
			
		||||
            invalidFields = Object.assign({}, invalidFields, field);
 | 
			
		||||
            if (typeof callback === 'function' && ++count === fields.length) {
 | 
			
		||||
              callback(valid, invalidFields);
 | 
			
		||||
            }
 | 
			
		||||
          });
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
      pending.catch(e => {
 | 
			
		||||
        if (console.error && process.env.NODE_ENV !== 'production') {
 | 
			
		||||
          console.error(e);
 | 
			
		||||
        }
 | 
			
		||||
        return e;
 | 
			
		||||
      });
 | 
			
		||||
      return pending;
 | 
			
		||||
      // names = [].concat(names);
 | 
			
		||||
      // const fields = this.fields.filter(field => names.indexOf(field.prop) !== -1);
 | 
			
		||||
      // if (!fields.length) {
 | 
			
		||||
      //   warning(false, 'FormModel', 'please pass correct props!');
 | 
			
		||||
      //   return;
 | 
			
		||||
      // }
 | 
			
		||||
      // fields.forEach(field => {
 | 
			
		||||
      //   field.validate('', cb);
 | 
			
		||||
      // });
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  render() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -59,6 +59,7 @@ export const FormItemProps = {
 | 
			
		|||
  rules: PropTypes.oneOfType([Array, Object]),
 | 
			
		||||
  autoLink: PropTypes.bool,
 | 
			
		||||
  required: PropTypes.bool,
 | 
			
		||||
  validateFirst: PropTypes.bool,
 | 
			
		||||
  validateStatus: PropTypes.oneOf(['', 'success', 'warning', 'error', 'validating']),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,61 @@
 | 
			
		|||
export function getValueFromEvent(e) {
 | 
			
		||||
  // To support custom element
 | 
			
		||||
  if (!e || !e.target) {
 | 
			
		||||
    return e;
 | 
			
		||||
  }
 | 
			
		||||
  const { target } = e;
 | 
			
		||||
  return target.type === 'checkbox' ? target.checked : target.value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function getErrorStrs(errors) {
 | 
			
		||||
  if (errors) {
 | 
			
		||||
    return errors.map(e => {
 | 
			
		||||
      if (e && e.message) {
 | 
			
		||||
        return e.message;
 | 
			
		||||
      }
 | 
			
		||||
      return e;
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
  return errors;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function getParams(ns, opt, cb) {
 | 
			
		||||
  let names = ns;
 | 
			
		||||
  let options = opt;
 | 
			
		||||
  let callback = cb;
 | 
			
		||||
  if (typeof names === 'string') {
 | 
			
		||||
    names = [names];
 | 
			
		||||
  }
 | 
			
		||||
  if (cb === undefined) {
 | 
			
		||||
    if (typeof names === 'function') {
 | 
			
		||||
      callback = names;
 | 
			
		||||
      options = {};
 | 
			
		||||
      names = undefined;
 | 
			
		||||
    } else if (Array.isArray(names)) {
 | 
			
		||||
      if (typeof options === 'function') {
 | 
			
		||||
        callback = options;
 | 
			
		||||
        options = {};
 | 
			
		||||
      } else {
 | 
			
		||||
        options = options || {};
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      callback = options;
 | 
			
		||||
      options = names || {};
 | 
			
		||||
      names = undefined;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return {
 | 
			
		||||
    names,
 | 
			
		||||
    options,
 | 
			
		||||
    callback,
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function hasRules(validate) {
 | 
			
		||||
  if (validate) {
 | 
			
		||||
    return validate.some(item => {
 | 
			
		||||
      return item.rules && item.rules.length;
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -76,7 +76,7 @@
 | 
			
		|||
    "@commitlint/config-conventional": "^8.0.0",
 | 
			
		||||
    "@octokit/rest": "^16.0.0",
 | 
			
		||||
    "@vue/cli-plugin-eslint": "^4.0.0",
 | 
			
		||||
    "@vue/compiler-sfc": "^3.0.0-beta.14",
 | 
			
		||||
    "@vue/compiler-sfc": "^3.0.0-beta.20",
 | 
			
		||||
    "@vue/server-test-utils": "1.0.0-beta.16",
 | 
			
		||||
    "@vue/test-utils": "^2.0.0-alpha.6",
 | 
			
		||||
    "acorn": "^7.0.0",
 | 
			
		||||
| 
						 | 
				
			
			@ -152,7 +152,7 @@
 | 
			
		|||
    "terser-webpack-plugin": "^3.0.3",
 | 
			
		||||
    "through2": "^3.0.0",
 | 
			
		||||
    "url-loader": "^3.0.0",
 | 
			
		||||
    "vue": "^3.0.0-beta.19",
 | 
			
		||||
    "vue": "^3.0.0-beta.20",
 | 
			
		||||
    "vue-antd-md-loader": "^1.1.0",
 | 
			
		||||
    "vue-clipboard2": "0.3.1",
 | 
			
		||||
    "vue-draggable-resizable": "^2.1.0",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue