mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-12-02 03:59:01 +08:00
* 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:
parent
5e99a93930
commit
6c0d6d302a
@ -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,
|
||||
};
|
||||
|
100
components/form/__tests__/__snapshots__/message.test.js.snap
Normal file
100
components/form/__tests__/__snapshots__/message.test.js.snap
Normal 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>
|
||||
`;
|
56
components/form/__tests__/message.test.js
Normal file
56
components/form/__tests__/message.test.js
Normal 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();
|
||||
});
|
||||
});
|
@ -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` |
|
||||
|
@ -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` |
|
||||
|
@ -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",
|
||||
|
2
typings/custom-typings.d.ts
vendored
2
typings/custom-typings.d.ts
vendored
@ -97,3 +97,5 @@ declare module "prop-types"
|
||||
declare module "lodash/debounce"
|
||||
|
||||
declare module "lodash/uniqBy"
|
||||
|
||||
declare module 'intersperse';
|
Loading…
Reference in New Issue
Block a user