Add feature: can use type ReactNode for message of rules (#10136) (#10395)

* Add feature: can use type ReactNode for message of rules (#10136)

* fix: Replace React.Fragment to span

* Add unit test for Form (Not passed)

* fix: unit test of Form

* fix: unit test of Form & remove demo

* fix: update unit test for Form

* Refine code for Form

* Add error check for getHelpMessage
This commit is contained in:
konakona 2018-05-08 01:00:00 -05:00 committed by 偏右
parent 5e99a93930
commit 6c0d6d302a
7 changed files with 176 additions and 11 deletions

View File

@ -2,6 +2,7 @@ import * as React from 'react';
import * as ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import intersperse from 'intersperse';
import Animate from 'rc-animate';
import Row from '../grid/row';
import Col, { ColProps } from '../grid/col';
@ -65,15 +66,20 @@ export default class FormItem extends React.Component<FormItemProps, any> {
);
}
getHelpMsg() {
const props = this.props;
const onlyControl = this.getOnlyControl();
if (props.help === undefined && onlyControl) {
getHelpMessage() {
const { help } = this.props;
if (help === undefined && this.getOnlyControl()) {
const errors = this.getField().errors;
return errors ? errors.map((e: any) => e.message).join(', ') : '';
if (errors) {
return intersperse(errors.map((e: any, index: number) => (
React.isValidElement(e.message)
? React.cloneElement(e.message, { key: index })
: e.message
)), ' ');
}
return '';
}
return props.help;
return help;
}
getControls(children: React.ReactNode, recursively: boolean) {
@ -129,7 +135,7 @@ export default class FormItem extends React.Component<FormItemProps, any> {
renderHelp() {
const prefixCls = this.props.prefixCls;
const help = this.getHelpMsg();
const help = this.getHelpMessage();
const children = help ? (
<div className={`${prefixCls}-explain`} key="help">
{help}
@ -306,7 +312,7 @@ export default class FormItem extends React.Component<FormItemProps, any> {
const style = props.style;
const itemClassName = {
[`${prefixCls}-item`]: true,
[`${prefixCls}-item-with-help`]: !!this.getHelpMsg() || this.state.helpShow,
[`${prefixCls}-item-with-help`]: !!this.getHelpMessage() || this.state.helpShow,
[`${prefixCls}-item-no-colon`]: !props.colon,
[`${props.className}`]: !!props.className,
};

View File

@ -0,0 +1,100 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Form should display custom message 1`] = `
<form
class="ant-form ant-form-horizontal"
>
<div
class="ant-row ant-form-item ant-form-item-with-help"
>
<div
class="ant-form-item-label"
>
<label
class=""
for="account"
title="Account"
>
Account
</label>
</div>
<div
class="ant-form-item-control-wrapper"
>
<div
class="ant-form-item-control has-error"
>
<span
class="ant-form-item-children"
>
<input
data-__field="[object Object]"
data-__meta="[object Object]"
id="account"
value="antd"
/>
</span>
<div
class="ant-form-explain show-help-enter"
>
<span>
Account does not exist,
<a
href="https://www.alipay.com/"
rel="noopener noreferrer"
target="_blank"
>
Forgot account?
</a>
</span>
</div>
</div>
</div>
</div>
</form>
`;
exports[`Form should display two message 1`] = `
<form
class="ant-form ant-form-horizontal"
>
<div
class="ant-row ant-form-item ant-form-item-with-help"
>
<div
class="ant-form-item-label"
>
<label
class=""
for="account"
title="Account"
>
Account
</label>
</div>
<div
class="ant-form-item-control-wrapper"
>
<div
class="ant-form-item-control has-error"
>
<span
class="ant-form-item-children"
>
<input
data-__field="[object Object]"
data-__meta="[object Object]"
id="account"
value="+=-/"
/>
</span>
<div
class="ant-form-explain show-help-enter"
>
Error message 1 Error message 2
</div>
</div>
</div>
</div>
</form>
`;

View File

@ -0,0 +1,56 @@
import React from 'react';
import { mount } from 'enzyme';
import Form from '..';
describe('Form', () => {
it('should display two message', () => {
const rules = [{
pattern: /^\w+$/,
message: 'Error message 1',
}, {
pattern: /^\w+$/,
message: 'Error message 2',
}];
let myForm;
const Form1 = Form.create()(({ form }) => {
myForm = form;
return (
<Form>
<Form.Item label="Account">
{form.getFieldDecorator('account', { initialValue: '+=-/', rules })(<input />)}
</Form.Item>
</Form>
);
});
const wrapper = mount(<Form1 />);
myForm.validateFields();
wrapper.update();
expect(wrapper.render()).toMatchSnapshot();
});
it('should display custom message', () => {
const rules = [{
pattern: /^$/,
message: (<span>Account does not exist, <a rel="noopener noreferrer" href="https://www.alipay.com/" target="_blank">Forgot account?</a></span>),
}];
let myForm;
const Form1 = Form.create()(({ form }) => {
myForm = form;
return (
<Form>
<Form.Item label="Account">
{form.getFieldDecorator('account', { initialValue: 'antd', rules })(<input />)}
</Form.Item>
</Form>
);
});
const wrapper = mount(<Form1 />);
myForm.validateFields();
wrapper.update();
expect(wrapper.render()).toMatchSnapshot();
});
});

View File

@ -147,7 +147,7 @@ Note:
| enum | validate a value from a list of possible values | string | - |
| len | validate an exact length of a field | number | - |
| max | validate a max length of a field | number | - |
| message | validation error message | string | - |
| message | validation error message | string\|ReactNode | - |
| min | validate a min length of a field | number | - |
| pattern | validate from a regular expression | RegExp | - |
| required | indicates whether field is required | boolean | `false` |

View File

@ -148,7 +148,7 @@ CustomizedForm = Form.create({})(CustomizedForm);
| enum | 枚举类型 | string | - |
| len | 字段长度 | number | - |
| max | 最大长度 | number | - |
| message | 校验文案 | string | - |
| message | 校验文案 | string\|ReactNode | - |
| min | 最小长度 | number | - |
| pattern | 正则表达式校验 | RegExp | - |
| required | 是否必选 | boolean | `false` |

View File

@ -46,6 +46,7 @@
"css-animation": "^1.2.5",
"dom-closest": "^0.2.0",
"enquire.js": "^2.1.1",
"intersperse": "^1.0.0",
"lodash": "^4.17.5",
"moment": "^2.19.3",
"omit.js": "^1.0.0",

View File

@ -97,3 +97,5 @@ declare module "prop-types"
declare module "lodash/debounce"
declare module "lodash/uniqBy"
declare module 'intersperse';