refactor: form

pull/2682/head
tangjinzhou 2020-07-12 16:13:59 +08:00
parent 130982a037
commit e79bfd8c96
4 changed files with 96 additions and 49 deletions

View File

@ -1,4 +1,5 @@
import { inject, provide } from 'vue'; import { inject, provide } from 'vue';
// import scrollIntoView from 'dom-scroll-into-view';
import PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
import classNames from 'classnames'; import classNames from 'classnames';
import { ColProps } from '../grid/Col'; import { ColProps } from '../grid/Col';
@ -99,7 +100,7 @@ const Form = {
this.$emit('submit', e); this.$emit('submit', e);
} }
}, },
resetFields(props = this.fields) { resetFields(props = []) {
if (!this.model) { if (!this.model) {
warning(false, 'FormModel', 'model is required for resetFields to work.'); warning(false, 'FormModel', 'model is required for resetFields to work.');
return; return;
@ -123,50 +124,53 @@ const Form = {
field.clearValidate(); field.clearValidate();
}); });
}, },
validate(callback) { validate() {
if (!this.model) { return this.validateField(...arguments);
warning(false, 'FormModel', 'model is required for resetFields to work.'); // if (!this.model) {
return; // warning(false, 'FormModel', 'model is required for resetFields to work.');
} // return;
let promise; // }
// if no callback, return promise // let promise;
if (typeof callback !== 'function' && window.Promise) { // // if no callback, return promise
promise = new window.Promise((resolve, reject) => { // if (typeof callback !== 'function' && window.Promise) {
callback = function(valid) { // promise = new window.Promise((resolve, reject) => {
valid ? resolve(valid) : reject(valid); // callback = function(valid) {
}; // valid ? resolve(valid) : reject(valid);
}); // };
} // });
let valid = true; // }
let count = 0; // let valid = true;
// fieldscallback // let count = 0;
if (this.fields.length === 0 && callback) { // // fieldscallback
callback(true); // if (this.fields.length === 0 && callback) {
} // callback(true);
let invalidFields = {}; // }
this.fields.forEach(field => { // let invalidFields = {};
field.validate('', (message, field) => { // this.fields.forEach(field => {
if (message) { // field.validate('', (message, field) => {
valid = false; // if (message) {
} // valid = false;
invalidFields = Object.assign({}, invalidFields, field); // }
if (typeof callback === 'function' && ++count === this.fields.length) { // invalidFields = Object.assign({}, invalidFields, field);
callback(valid, invalidFields); // if (typeof callback === 'function' && ++count === this.fields.length) {
} // callback(valid, invalidFields);
}); // }
}); // });
if (promise) { // });
return promise; // if (promise) {
} // return promise;
// }
}, },
scrollToField() {}, scrollToField() {},
getFieldsValue(allFields) { getFieldsValue(allFields) {
return allFields.map(({ prop, fieldValue }) => { const values = {};
return { [prop]: fieldValue }; allFields.forEach(({ prop, fieldValue }) => {
values[prop] = fieldValue;
}); });
return values;
}, },
validateFields() { validateFields() {
this.validateField(...arguments); return this.validateField(...arguments);
}, },
validateField(ns, opt, cb) { validateField(ns, opt, cb) {
const pending = new Promise((resolve, reject) => { const pending = new Promise((resolve, reject) => {
@ -201,18 +205,18 @@ const Form = {
return !!field.validateFirst; return !!field.validateFirst;
}); });
} }
let invalidFields = {}; let fieldsErrors = {};
let valid = true; let valid = true;
let count = 0; let count = 0;
fields.forEach(field => { fields.forEach(field => {
field.validate('', (message, field) => { field.validate('', errors => {
if (message) { if (errors) {
valid = false; valid = false;
fieldsErrors[field.prop] = errors;
} }
// TODO
invalidFields = Object.assign({}, invalidFields, field); if (++count === fields.length) {
if (typeof callback === 'function' && ++count === fields.length) { callback(valid ? null : fieldsErrors, this.getFieldsValue(fields));
callback(valid, invalidFields);
} }
}); });
}); });

View File

@ -152,10 +152,10 @@ export default {
} }
const model = {}; const model = {};
model[this.prop] = this.fieldValue; model[this.prop] = this.fieldValue;
validator.validate(model, { firstFields: true }, (errors, invalidFields) => { validator.validate(model, {}, errors => {
this.validateState = errors ? 'error' : 'success'; this.validateState = errors ? 'error' : 'success';
this.validateMessage = errors ? errors[0].message : ''; this.validateMessage = errors ? errors[0].message : '';
callback(this.validateMessage, invalidFields); callback(errors);
this.FormContext && this.FormContext &&
this.FormContext.$emit && this.FormContext.$emit &&
this.FormContext.$emit('validate', this.prop, !errors, this.validateMessage || null); this.FormContext.$emit('validate', this.prop, !errors, this.validateMessage || null);

View File

@ -59,3 +59,46 @@ export function hasRules(validate) {
} }
return false; return false;
} }
export function computedStyle(el, prop) {
const getComputedStyle = window.getComputedStyle;
const style =
// If we have getComputedStyle
getComputedStyle
? // Query it
// TODO: From CSS-Query notes, we might need (node, null) for FF
getComputedStyle(el)
: // Otherwise, we are in IE and use currentStyle
el.currentStyle;
if (style) {
return style[
// Switch to camelCase for CSSOM
// DEV: Grabbed from jQuery
// https://github.com/jquery/jquery/blob/1.9-stable/src/css.js#L191-L194
// https://github.com/jquery/jquery/blob/1.9-stable/src/core.js#L593-L597
prop.replace(/-(\w)/gi, (word, letter) => {
return letter.toUpperCase();
})
];
}
return undefined;
}
export function getScrollableContainer(n) {
let node = n;
let nodeName;
/* eslint no-cond-assign:0 */
while ((nodeName = node.nodeName.toLowerCase()) !== 'body') {
const overflowY = computedStyle(node, 'overflowY');
// https://stackoverflow.com/a/36900407/3040605
if (
node !== n &&
(overflowY === 'auto' || overflowY === 'scroll') &&
node.scrollHeight > node.clientHeight
) {
return node;
}
node = node.parentNode;
}
return nodeName === 'body' ? node.ownerDocument : node;
}

View File

@ -4,7 +4,7 @@
</div> </div>
</template> </template>
<script> <script>
import demo from '../antdv-demo/docs/cascader/demo/index'; import demo from '../antdv-demo/docs/form-model/demo/custom-validation';
export default { export default {
components: { components: {