From 93127d611303cd018787d734d66ab40929a85351 Mon Sep 17 00:00:00 2001 From: Justin Kahn Date: Wed, 15 May 2019 11:40:39 +0800 Subject: [PATCH 1/3] fix(Field): no react key props for errors --- src/field/index.js | 2 +- src/field/utils.js | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/field/index.js b/src/field/index.js index 25a9db54aa..4c1ba0ac5d 100644 --- a/src/field/index.js +++ b/src/field/index.js @@ -480,7 +480,7 @@ class Field { // update error in every Field Object.keys(errorsGroup).forEach(i => { const field = this._get(i); - field.errors = errorsGroup[i].errors; + field.errors = getErrorStrs(errorsGroup[i].errors); field.state = 'error'; }); } diff --git a/src/field/utils.js b/src/field/utils.js index 134a3d126c..b3d077038f 100644 --- a/src/field/utils.js +++ b/src/field/utils.js @@ -25,18 +25,18 @@ export function getValueFromEvent(e) { return target.value; } +function cloneAndAddKey(element) { + if (element && isValidElement(element) && !element.props.key) { + return cloneElement(element, { key: 'error' }); + } + return element; +} + export function getErrorStrs(errors) { if (errors) { - return errors.map(e => { - if ('message' in e) { - const message = e.message; - // add key for jsx to ignore key warning - if (message && isValidElement(message) && !message.props.key) { - return cloneElement(message, { key: 'error' }); - } - return message; - } - return e; + return errors.map(function(e) { + const message = e.message || e; + return cloneAndAddKey(message); }); } return errors; From 5560353b3b3b29d4decacac6112437e15249837a Mon Sep 17 00:00:00 2001 From: Justin Kahn Date: Wed, 15 May 2019 14:31:10 +0800 Subject: [PATCH 2/3] docs(Form): custom validation error --- docs/form/demo/validate-custom-error.md | 64 +++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 docs/form/demo/validate-custom-error.md diff --git a/docs/form/demo/validate-custom-error.md b/docs/form/demo/validate-custom-error.md new file mode 100644 index 0000000000..a14a04baa0 --- /dev/null +++ b/docs/form/demo/validate-custom-error.md @@ -0,0 +1,64 @@ +# 校验 + +- order: 9 + +基本的表单校验例子。 + +:::lang=en-us +# Validate + +- order: 9 + +Basic usage of validation. +::: + +--- + +````jsx +import { Form, Input, Field } from '@alifd/next'; + + +const FormItem = Form.Item; + +const formItemLayout = { + labelCol: { + span: 6 + }, + wrapperCol: { + span: 14 + } +}; + +class BasicDemo extends React.Component { + field = new Field(this); + + render() { + const { + field, + field: { + init, + } + } = this; + return ( +
+ + + This is a CUSTOM error); + } + }] + })} /> + + + Submit + Reset + +
+ ); + } +} + +ReactDOM.render(, mountNode); +```` From 4d65cffa7fe581ee9604b54b7b0fd5fe2fbea894 Mon Sep 17 00:00:00 2001 From: Justin Kahn Date: Wed, 15 May 2019 16:32:13 +0800 Subject: [PATCH 3/3] test(Field): `getErrorStrs` tests - clean up eslint errors in other tests --- src/field/utils.js | 2 +- test/field/index-spec.js | 66 ++++++++++++++++++++------------------ test/field/options-spec.js | 33 ++++++++++--------- test/field/rules-spec.js | 12 +++---- test/field/utils-spec.js | 58 +++++++++++++++++++++++++++++++++ 5 files changed, 116 insertions(+), 55 deletions(-) create mode 100644 test/field/utils-spec.js diff --git a/src/field/utils.js b/src/field/utils.js index b3d077038f..1ceda8ae89 100644 --- a/src/field/utils.js +++ b/src/field/utils.js @@ -26,7 +26,7 @@ export function getValueFromEvent(e) { } function cloneAndAddKey(element) { - if (element && isValidElement(element) && !element.props.key) { + if (element && isValidElement(element)) { return cloneElement(element, { key: 'error' }); } return element; diff --git a/test/field/index-spec.js b/test/field/index-spec.js index 9a5989362e..b7dc1d444e 100644 --- a/test/field/index-spec.js +++ b/test/field/index-spec.js @@ -11,9 +11,11 @@ Enzyme.configure({ adapter: new Adapter() }); const FormItem = Form.Item; +/* eslint-disable react/jsx-filename-extension */ +/*global describe it */ describe('field', () => { describe('render', () => { - it('should support Form', done => { + it('should support Form', function(done) { class Demo extends React.Component { constructor(props) { super(props); @@ -64,7 +66,7 @@ describe('field', () => { done(); }); - it('should support PureComponent', done => { + it('should support PureComponent', function(done) { class Demo extends React.PureComponent { constructor(props) { super(props); @@ -95,7 +97,7 @@ describe('field', () => { done(); }); - it('should support origin input/checkbox/radio', done => { + it('should support origin input/checkbox/radio', function(done) { class Demo extends React.Component { constructor(props) { super(props); @@ -155,8 +157,8 @@ describe('field', () => { }); }); describe('init', () => { - it('init(input)', done => { - let field = new Field(); + it('init(input)', function(done) { + let field = new Field(this); let inited = field.init('input'); assert(typeof inited['ref'] === 'function'); @@ -177,8 +179,8 @@ describe('field', () => { done(); }); - it('initValue', done => { - let field = new Field(); + it('initValue', function(done) { + let field = new Field(this); let inited = field.init('input', { initValue: 2 }); assert(inited.value === 2); @@ -189,8 +191,8 @@ describe('field', () => { done(); }); - it('valueName', done => { - let field = new Field(); + it('valueName', function(done) { + let field = new Field(this); let inited = field.init('input', { initValue: true, valueName: 'checked', @@ -200,8 +202,8 @@ describe('field', () => { done(); }); - it('props', done => { - let field = new Field(); + it('props', function(done) { + let field = new Field(this); let inited = field.init('input', { initValue: true, valueName: 'checked', @@ -216,9 +218,9 @@ describe('field', () => { done(); }); - it('custom Event: onChange', done => { + it('custom Event: onChange', function(done) { const onChange = sinon.spy(); - let field = new Field(null, { onChange }); + let field = new Field(this, { onChange }); let inited = field.init('input', { props: { onChange, @@ -234,7 +236,7 @@ describe('field', () => { assert(field.getValue('input') === 'test'); assert(onChange.callCount === 2); - let field2 = new Field(null, { + let field2 = new Field(this, { onChange: (name, value) => { assert(value === 'test'); }, @@ -260,8 +262,8 @@ describe('field', () => { done(); }); - it('getValueFromEvent', done => { - let field = new Field(null, { + it('getValueFromEvent', function(done) { + let field = new Field(this, { onChange: (name, value) => { assert(value === 'test!'); }, @@ -286,8 +288,8 @@ describe('field', () => { done(); }); - it('rules', done => { - let field = new Field(); + it('rules', function(done) { + let field = new Field(this); field.init('input', { rules: [ { @@ -311,8 +313,8 @@ describe('field', () => { }); describe('behaviour', () => { - it('getValue & getValues & setValue & setValues', done => { - let field = new Field(); + it('getValue & getValues & setValue & setValues', function(done) { + let field = new Field(this); field.init('input', { initValue: 1 }); field.init('input2', { initValue: 2 }); field.init('input3.name', { initValue: 3 }); @@ -331,8 +333,8 @@ describe('field', () => { done(); }); - it('setError & setErrors & getError & getErrors', done => { - let field = new Field(); + it('setError & setErrors & getError & getErrors', function(done) { + let field = new Field(this); field.setError('input', 'error1'); field.init('input'); @@ -356,8 +358,8 @@ describe('field', () => { done(); }); - it('getState', done => { - let field = new Field(); + it('getState', function(done) { + let field = new Field(this); field.init('input'); @@ -369,8 +371,8 @@ describe('field', () => { done(); }); - it('validate', done => { - let field = new Field(); + it('validate', function(done) { + let field = new Field(this); let inited = field.init('input', { rules: [{ required: true, message: 'cant be null' }], }); @@ -413,8 +415,8 @@ describe('field', () => { done(); }); - it('reset', done => { - let field = new Field(); + it('reset', function(done) { + let field = new Field(this); field.init('input', { initValue: '1' }); field.reset(); @@ -428,8 +430,8 @@ describe('field', () => { done(); }); - it('remove', done => { - let field = new Field(); + it('remove', function(done) { + let field = new Field(this); field.init('input', { initValue: 1 }); field.init('input2', { initValue: 1 }); field.init('input3', { initValue: 1 }); @@ -444,8 +446,8 @@ describe('field', () => { done(); }); - it('spliceArray', done => { - let field = new Field(); + it('spliceArray', function(done) { + let field = new Field(this); field.init('input.0', { initValue: 0 }); field.init('input.1', { initValue: 1 }); field.init('input.2', { initValue: 2 }); diff --git a/test/field/options-spec.js b/test/field/options-spec.js index 69087ebb46..dbd20d70b3 100644 --- a/test/field/options-spec.js +++ b/test/field/options-spec.js @@ -7,8 +7,9 @@ import Field from '../../src/field/index'; Enzyme.configure({ adapter: new Adapter() }); +/*global describe it */ describe('options', () => { - it('should support autoUnmount', done => { + it('should support autoUnmount', function(done) { class Demo extends React.Component { state = { show: true, @@ -41,7 +42,7 @@ describe('options', () => { wrapper.find('button').simulate('click'); }); - it('should support autoUnmount with same name', done => { + it('should support autoUnmount with same name', function(done) { class Demo extends React.Component { state = { show: true, @@ -77,7 +78,7 @@ describe('options', () => { done(); }); - it('should support autoUnmount=false', done => { + it('should support autoUnmount=false', function(done) { class Demo extends React.Component { state = { show: true, @@ -96,7 +97,7 @@ describe('options', () => { ) : null}