2017-11-17 14:38:54 +08:00
|
|
|
|
import * as React from 'react';
|
|
|
|
|
import * as ReactDOM from 'react-dom';
|
2018-08-07 21:07:52 +08:00
|
|
|
|
import * as PropTypes from 'prop-types';
|
2015-11-24 20:03:57 +08:00
|
|
|
|
import classNames from 'classnames';
|
2017-09-23 15:21:11 +08:00
|
|
|
|
import Animate from 'rc-animate';
|
2019-11-06 23:30:41 +08:00
|
|
|
|
import omit from 'omit.js';
|
2017-05-15 11:31:48 +08:00
|
|
|
|
import Row from '../grid/row';
|
|
|
|
|
import Col, { ColProps } from '../grid/col';
|
2018-07-25 11:42:26 +08:00
|
|
|
|
import Icon from '../icon';
|
2018-12-05 19:12:18 +08:00
|
|
|
|
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
|
|
|
|
import warning from '../_util/warning';
|
2018-12-22 21:21:42 +08:00
|
|
|
|
import { tuple } from '../_util/type';
|
2019-02-25 19:04:09 +08:00
|
|
|
|
import { FIELD_META_PROP, FIELD_DATA_PROP } from './constants';
|
2019-08-14 18:21:24 +08:00
|
|
|
|
import FormContext, { FormContextProps } from './context';
|
2018-12-22 21:21:42 +08:00
|
|
|
|
|
2018-12-27 11:46:22 +08:00
|
|
|
|
const ValidateStatuses = tuple('success', 'warning', 'error', 'validating', '');
|
2015-10-09 13:53:04 +08:00
|
|
|
|
|
2019-11-04 11:24:23 +08:00
|
|
|
|
const FormLabelAligns = tuple('left', 'right');
|
|
|
|
|
|
2019-11-11 10:10:53 +08:00
|
|
|
|
export type FormLabelAlign = typeof FormLabelAligns[number];
|
2019-04-15 12:10:04 +08:00
|
|
|
|
|
2016-08-19 16:43:32 +08:00
|
|
|
|
export interface FormItemProps {
|
|
|
|
|
prefixCls?: string;
|
2017-10-31 10:37:49 +08:00
|
|
|
|
className?: string;
|
2016-08-22 17:26:14 +08:00
|
|
|
|
id?: string;
|
2019-05-06 12:04:39 +08:00
|
|
|
|
htmlFor?: string;
|
2016-10-24 12:04:26 +08:00
|
|
|
|
label?: React.ReactNode;
|
2019-04-15 12:10:04 +08:00
|
|
|
|
labelAlign?: FormLabelAlign;
|
2017-06-28 15:03:52 +08:00
|
|
|
|
labelCol?: ColProps;
|
|
|
|
|
wrapperCol?: ColProps;
|
2016-08-19 16:43:32 +08:00
|
|
|
|
help?: React.ReactNode;
|
2017-02-27 10:20:46 +08:00
|
|
|
|
extra?: React.ReactNode;
|
2019-11-11 10:10:53 +08:00
|
|
|
|
validateStatus?: typeof ValidateStatuses[number];
|
2016-08-19 16:43:32 +08:00
|
|
|
|
hasFeedback?: boolean;
|
|
|
|
|
required?: boolean;
|
|
|
|
|
style?: React.CSSProperties;
|
2016-08-22 17:26:14 +08:00
|
|
|
|
colon?: boolean;
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-18 22:20:52 +08:00
|
|
|
|
function intersperseSpace<T>(list: Array<T>): Array<T | string> {
|
|
|
|
|
return list.reduce((current, item) => [...current, ' ', item], []).slice(1);
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-19 16:43:32 +08:00
|
|
|
|
export default class FormItem extends React.Component<FormItemProps, any> {
|
2016-04-12 16:06:17 +08:00
|
|
|
|
static defaultProps = {
|
|
|
|
|
hasFeedback: false,
|
2016-07-13 11:14:24 +08:00
|
|
|
|
};
|
2016-04-12 16:06:17 +08:00
|
|
|
|
|
|
|
|
|
static propTypes = {
|
2017-04-12 04:49:08 +08:00
|
|
|
|
prefixCls: PropTypes.string,
|
|
|
|
|
label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
|
|
|
|
labelCol: PropTypes.object,
|
|
|
|
|
help: PropTypes.oneOfType([PropTypes.node, PropTypes.bool]),
|
2018-12-22 21:21:42 +08:00
|
|
|
|
validateStatus: PropTypes.oneOf(ValidateStatuses),
|
2017-04-12 04:49:08 +08:00
|
|
|
|
hasFeedback: PropTypes.bool,
|
|
|
|
|
wrapperCol: PropTypes.object,
|
|
|
|
|
className: PropTypes.string,
|
|
|
|
|
id: PropTypes.string,
|
|
|
|
|
children: PropTypes.node,
|
|
|
|
|
colon: PropTypes.bool,
|
2016-07-13 11:14:24 +08:00
|
|
|
|
};
|
2016-04-12 16:06:17 +08:00
|
|
|
|
|
2018-05-10 21:48:11 +08:00
|
|
|
|
helpShow = false;
|
2018-03-14 17:43:02 +08:00
|
|
|
|
|
2016-10-20 16:24:48 +08:00
|
|
|
|
componentDidMount() {
|
2019-05-06 12:04:39 +08:00
|
|
|
|
const { children, help, validateStatus, id } = this.props;
|
2016-11-01 11:10:11 +08:00
|
|
|
|
warning(
|
2019-02-22 14:01:03 +08:00
|
|
|
|
this.getControls(children, true).length <= 1 ||
|
2019-12-01 15:29:53 +08:00
|
|
|
|
help !== undefined ||
|
|
|
|
|
validateStatus !== undefined,
|
2019-02-27 15:32:29 +08:00
|
|
|
|
'Form.Item',
|
|
|
|
|
'Cannot generate `validateStatus` and `help` automatically, ' +
|
2018-12-07 20:02:01 +08:00
|
|
|
|
'while there are more than one `getFieldDecorator` in it.',
|
2016-11-01 11:10:11 +08:00
|
|
|
|
);
|
2019-05-06 12:04:39 +08:00
|
|
|
|
|
|
|
|
|
warning(
|
|
|
|
|
!id,
|
|
|
|
|
'Form.Item',
|
|
|
|
|
'`id` is deprecated for its label `htmlFor`. Please use `htmlFor` directly.',
|
|
|
|
|
);
|
2016-10-20 16:24:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-05-08 14:00:00 +08:00
|
|
|
|
getHelpMessage() {
|
|
|
|
|
const { help } = this.props;
|
|
|
|
|
if (help === undefined && this.getOnlyControl()) {
|
2019-03-08 11:25:37 +08:00
|
|
|
|
const { errors } = this.getField();
|
2018-05-08 14:00:00 +08:00
|
|
|
|
if (errors) {
|
2018-12-18 22:20:52 +08:00
|
|
|
|
return intersperseSpace(
|
|
|
|
|
errors.map((e: any, index: number) => {
|
|
|
|
|
let node: React.ReactElement<any> | null = null;
|
|
|
|
|
|
|
|
|
|
if (React.isValidElement(e)) {
|
|
|
|
|
node = e;
|
|
|
|
|
} else if (React.isValidElement(e.message)) {
|
|
|
|
|
node = e.message;
|
|
|
|
|
}
|
2019-08-06 15:02:05 +08:00
|
|
|
|
// eslint-disable-next-line react/no-array-index-key
|
2018-12-18 22:20:52 +08:00
|
|
|
|
return node ? React.cloneElement(node, { key: index }) : e.message;
|
|
|
|
|
}),
|
2018-12-07 20:02:01 +08:00
|
|
|
|
);
|
2018-05-08 14:00:00 +08:00
|
|
|
|
}
|
|
|
|
|
return '';
|
2016-01-21 16:23:35 +08:00
|
|
|
|
}
|
2018-05-08 14:00:00 +08:00
|
|
|
|
return help;
|
2016-01-21 16:23:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
2017-11-21 20:45:24 +08:00
|
|
|
|
getControls(children: React.ReactNode, recursively: boolean) {
|
2016-10-24 12:04:26 +08:00
|
|
|
|
let controls: React.ReactElement<any>[] = [];
|
2016-10-20 16:24:48 +08:00
|
|
|
|
const childrenArray = React.Children.toArray(children);
|
|
|
|
|
for (let i = 0; i < childrenArray.length; i++) {
|
|
|
|
|
if (!recursively && controls.length > 0) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const child = childrenArray[i] as React.ReactElement<any>;
|
2018-12-07 20:02:01 +08:00
|
|
|
|
if (
|
|
|
|
|
child.type &&
|
|
|
|
|
((child.type as any) === FormItem || (child.type as any).displayName === 'FormItem')
|
|
|
|
|
) {
|
2016-10-20 16:24:48 +08:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (!child.props) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2018-12-07 20:02:01 +08:00
|
|
|
|
if (FIELD_META_PROP in child.props) {
|
|
|
|
|
// And means FIELD_DATA_PROP in child.props, too.
|
2016-10-20 16:24:48 +08:00
|
|
|
|
controls.push(child);
|
|
|
|
|
} else if (child.props.children) {
|
|
|
|
|
controls = controls.concat(this.getControls(child.props.children, recursively));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return controls;
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-12 16:06:17 +08:00
|
|
|
|
getOnlyControl() {
|
2016-10-20 16:24:48 +08:00
|
|
|
|
const child = this.getControls(this.props.children, false)[0];
|
2016-04-12 16:06:17 +08:00
|
|
|
|
return child !== undefined ? child : null;
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-21 20:45:24 +08:00
|
|
|
|
getChildProp(prop: string) {
|
2016-08-24 16:09:55 +08:00
|
|
|
|
const child = this.getOnlyControl() as React.ReactElement<any>;
|
2016-04-12 16:06:17 +08:00
|
|
|
|
return child && child.props && child.props[prop];
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-28 21:43:45 +08:00
|
|
|
|
getId() {
|
2016-04-12 16:06:17 +08:00
|
|
|
|
return this.getChildProp('id');
|
2016-01-28 21:43:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
2016-02-01 10:23:06 +08:00
|
|
|
|
getMeta() {
|
2016-07-07 16:59:47 +08:00
|
|
|
|
return this.getChildProp(FIELD_META_PROP);
|
2016-02-01 10:23:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
2017-10-31 10:37:49 +08:00
|
|
|
|
getField() {
|
|
|
|
|
return this.getChildProp(FIELD_DATA_PROP);
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-05 18:38:10 +08:00
|
|
|
|
getValidateStatus() {
|
|
|
|
|
const onlyControl = this.getOnlyControl();
|
|
|
|
|
if (!onlyControl) {
|
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
const field = this.getField();
|
|
|
|
|
if (field.validating) {
|
|
|
|
|
return 'validating';
|
|
|
|
|
}
|
|
|
|
|
if (field.errors) {
|
|
|
|
|
return 'error';
|
|
|
|
|
}
|
|
|
|
|
const fieldValue = 'value' in field ? field.value : this.getMeta().initialValue;
|
|
|
|
|
if (fieldValue !== undefined && fieldValue !== null && fieldValue !== '') {
|
|
|
|
|
return 'success';
|
|
|
|
|
}
|
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Resolve duplicated ids bug between different forms
|
|
|
|
|
// https://github.com/ant-design/ant-design/issues/7351
|
|
|
|
|
onLabelClick = () => {
|
|
|
|
|
const id = this.props.id || this.getId();
|
|
|
|
|
if (!id) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const formItemNode = ReactDOM.findDOMNode(this) as Element;
|
|
|
|
|
const control = formItemNode.querySelector(`[id="${id}"]`) as HTMLElement;
|
|
|
|
|
if (control && control.focus) {
|
|
|
|
|
control.focus();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2018-03-14 17:43:02 +08:00
|
|
|
|
onHelpAnimEnd = (_key: string, helpShow: boolean) => {
|
2018-05-10 21:48:11 +08:00
|
|
|
|
this.helpShow = helpShow;
|
|
|
|
|
if (!helpShow) {
|
|
|
|
|
this.setState({});
|
|
|
|
|
}
|
2018-12-07 20:02:01 +08:00
|
|
|
|
};
|
2018-03-14 17:43:02 +08:00
|
|
|
|
|
2019-08-05 18:38:10 +08:00
|
|
|
|
isRequired() {
|
|
|
|
|
const { required } = this.props;
|
|
|
|
|
if (required !== undefined) {
|
|
|
|
|
return required;
|
|
|
|
|
}
|
|
|
|
|
if (this.getOnlyControl()) {
|
|
|
|
|
const meta = this.getMeta() || {};
|
|
|
|
|
const validate = meta.validate || [];
|
|
|
|
|
|
|
|
|
|
return validate
|
|
|
|
|
.filter((item: any) => !!item.rules)
|
|
|
|
|
.some((item: any) => {
|
|
|
|
|
return item.rules.some((rule: any) => rule.required);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-05 19:12:18 +08:00
|
|
|
|
renderHelp(prefixCls: string) {
|
2018-05-08 14:00:00 +08:00
|
|
|
|
const help = this.getHelpMessage();
|
2017-09-22 21:50:14 +08:00
|
|
|
|
const children = help ? (
|
2019-02-18 16:42:02 +08:00
|
|
|
|
<div className={`${prefixCls}-explain`} key="help">
|
2017-09-22 21:47:28 +08:00
|
|
|
|
{help}
|
2019-02-18 16:42:02 +08:00
|
|
|
|
</div>
|
2017-09-22 21:47:28 +08:00
|
|
|
|
) : null;
|
2018-05-10 21:48:11 +08:00
|
|
|
|
if (children) {
|
|
|
|
|
this.helpShow = !!children;
|
|
|
|
|
}
|
2017-09-22 21:50:14 +08:00
|
|
|
|
return (
|
2019-02-18 16:42:02 +08:00
|
|
|
|
<Animate
|
|
|
|
|
transitionName="show-help"
|
|
|
|
|
component=""
|
|
|
|
|
transitionAppear
|
|
|
|
|
key="help"
|
|
|
|
|
onEnd={this.onHelpAnimEnd}
|
|
|
|
|
>
|
|
|
|
|
{children}
|
|
|
|
|
</Animate>
|
2017-09-22 21:50:14 +08:00
|
|
|
|
);
|
2015-10-09 13:53:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-05 19:12:18 +08:00
|
|
|
|
renderExtra(prefixCls: string) {
|
|
|
|
|
const { extra } = this.props;
|
2018-12-07 20:02:01 +08:00
|
|
|
|
return extra ? <div className={`${prefixCls}-extra`}>{extra}</div> : null;
|
2016-04-25 16:25:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-07 20:02:01 +08:00
|
|
|
|
renderValidateWrapper(
|
|
|
|
|
prefixCls: string,
|
|
|
|
|
c1: React.ReactNode,
|
|
|
|
|
c2: React.ReactNode,
|
|
|
|
|
c3: React.ReactNode,
|
|
|
|
|
) {
|
2019-03-08 11:25:37 +08:00
|
|
|
|
const { props } = this;
|
2017-10-31 10:37:49 +08:00
|
|
|
|
const onlyControl = this.getOnlyControl;
|
2018-12-07 20:02:01 +08:00
|
|
|
|
const validateStatus =
|
|
|
|
|
props.validateStatus === undefined && onlyControl
|
|
|
|
|
? this.getValidateStatus()
|
|
|
|
|
: props.validateStatus;
|
2016-01-21 16:23:35 +08:00
|
|
|
|
|
2018-12-05 19:12:18 +08:00
|
|
|
|
let classes = `${prefixCls}-item-control`;
|
2016-01-21 16:23:35 +08:00
|
|
|
|
if (validateStatus) {
|
2018-12-05 19:12:18 +08:00
|
|
|
|
classes = classNames(`${prefixCls}-item-control`, {
|
2017-10-31 10:37:49 +08:00
|
|
|
|
'has-feedback': props.hasFeedback || validateStatus === 'validating',
|
|
|
|
|
'has-success': validateStatus === 'success',
|
|
|
|
|
'has-warning': validateStatus === 'warning',
|
|
|
|
|
'has-error': validateStatus === 'error',
|
|
|
|
|
'is-validating': validateStatus === 'validating',
|
|
|
|
|
});
|
2015-10-09 13:53:04 +08:00
|
|
|
|
}
|
2018-07-25 11:42:26 +08:00
|
|
|
|
|
|
|
|
|
let iconType = '';
|
|
|
|
|
switch (validateStatus) {
|
|
|
|
|
case 'success':
|
2018-08-24 17:36:22 +08:00
|
|
|
|
iconType = 'check-circle';
|
2018-07-25 11:42:26 +08:00
|
|
|
|
break;
|
|
|
|
|
case 'warning':
|
2018-08-24 17:36:22 +08:00
|
|
|
|
iconType = 'exclamation-circle';
|
2018-07-25 11:42:26 +08:00
|
|
|
|
break;
|
|
|
|
|
case 'error':
|
2018-08-24 17:36:22 +08:00
|
|
|
|
iconType = 'close-circle';
|
2018-07-25 11:42:26 +08:00
|
|
|
|
break;
|
|
|
|
|
case 'validating':
|
2018-08-24 17:36:22 +08:00
|
|
|
|
iconType = 'loading';
|
2018-07-25 11:42:26 +08:00
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
iconType = '';
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-07 20:02:01 +08:00
|
|
|
|
const icon =
|
|
|
|
|
props.hasFeedback && iconType ? (
|
|
|
|
|
<span className={`${prefixCls}-item-children-icon`}>
|
|
|
|
|
<Icon type={iconType} theme={iconType === 'loading' ? 'outlined' : 'filled'} />
|
|
|
|
|
</span>
|
|
|
|
|
) : null;
|
2018-07-25 11:42:26 +08:00
|
|
|
|
|
2015-10-30 11:36:11 +08:00
|
|
|
|
return (
|
2018-01-12 16:33:04 +08:00
|
|
|
|
<div className={classes}>
|
2018-12-05 19:12:18 +08:00
|
|
|
|
<span className={`${prefixCls}-item-children`}>
|
2018-12-07 20:02:01 +08:00
|
|
|
|
{c1}
|
|
|
|
|
{icon}
|
2018-07-25 11:42:26 +08:00
|
|
|
|
</span>
|
2018-12-07 20:02:01 +08:00
|
|
|
|
{c2}
|
|
|
|
|
{c3}
|
2015-10-30 11:36:11 +08:00
|
|
|
|
</div>
|
|
|
|
|
);
|
2015-10-09 13:53:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-05 19:12:18 +08:00
|
|
|
|
renderWrapper(prefixCls: string, children: React.ReactNode) {
|
2015-10-31 08:43:38 +08:00
|
|
|
|
return (
|
2019-03-04 14:51:40 +08:00
|
|
|
|
<FormContext.Consumer key="wrapper">
|
2019-02-25 19:04:09 +08:00
|
|
|
|
{({ wrapperCol: contextWrapperCol, vertical }: FormContextProps) => {
|
|
|
|
|
const { wrapperCol } = this.props;
|
|
|
|
|
const mergedWrapperCol: ColProps =
|
|
|
|
|
('wrapperCol' in this.props ? wrapperCol : contextWrapperCol) || {};
|
|
|
|
|
|
|
|
|
|
const className = classNames(
|
|
|
|
|
`${prefixCls}-item-control-wrapper`,
|
|
|
|
|
mergedWrapperCol.className,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// No pass FormContext since it's useless
|
|
|
|
|
return (
|
|
|
|
|
<FormContext.Provider value={{ vertical }}>
|
2019-03-04 14:51:40 +08:00
|
|
|
|
<Col {...mergedWrapperCol} className={className}>
|
2019-02-25 19:04:09 +08:00
|
|
|
|
{children}
|
|
|
|
|
</Col>
|
|
|
|
|
</FormContext.Provider>
|
|
|
|
|
);
|
|
|
|
|
}}
|
|
|
|
|
</FormContext.Consumer>
|
2015-10-31 08:43:38 +08:00
|
|
|
|
);
|
2015-10-09 13:53:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-05 19:12:18 +08:00
|
|
|
|
renderLabel(prefixCls: string) {
|
2019-02-25 19:04:09 +08:00
|
|
|
|
return (
|
2019-03-04 14:51:40 +08:00
|
|
|
|
<FormContext.Consumer key="label">
|
2019-03-08 15:21:36 +08:00
|
|
|
|
{({
|
|
|
|
|
vertical,
|
2019-04-15 12:10:04 +08:00
|
|
|
|
labelAlign: contextLabelAlign,
|
2019-03-08 15:21:36 +08:00
|
|
|
|
labelCol: contextLabelCol,
|
|
|
|
|
colon: contextColon,
|
|
|
|
|
}: FormContextProps) => {
|
2019-05-06 12:04:39 +08:00
|
|
|
|
const { label, labelCol, labelAlign, colon, id, htmlFor } = this.props;
|
2019-02-25 19:04:09 +08:00
|
|
|
|
const required = this.isRequired();
|
|
|
|
|
|
|
|
|
|
const mergedLabelCol: ColProps =
|
|
|
|
|
('labelCol' in this.props ? labelCol : contextLabelCol) || {};
|
|
|
|
|
|
2019-04-15 12:10:04 +08:00
|
|
|
|
const mergedLabelAlign: FormLabelAlign | undefined =
|
|
|
|
|
'labelAlign' in this.props ? labelAlign : contextLabelAlign;
|
|
|
|
|
|
2019-03-08 15:21:36 +08:00
|
|
|
|
const labelClsBasic = `${prefixCls}-item-label`;
|
|
|
|
|
const labelColClassName = classNames(
|
|
|
|
|
labelClsBasic,
|
2019-04-15 12:10:04 +08:00
|
|
|
|
mergedLabelAlign === 'left' && `${labelClsBasic}-left`,
|
2019-03-08 15:21:36 +08:00
|
|
|
|
mergedLabelCol.className,
|
|
|
|
|
);
|
2019-02-25 19:04:09 +08:00
|
|
|
|
|
|
|
|
|
let labelChildren = label;
|
|
|
|
|
// Keep label is original where there should have no colon
|
2019-03-08 11:25:37 +08:00
|
|
|
|
const computedColon = colon === true || (contextColon !== false && colon !== false);
|
|
|
|
|
const haveColon = computedColon && !vertical;
|
2019-02-25 19:04:09 +08:00
|
|
|
|
// Remove duplicated user input colon
|
|
|
|
|
if (haveColon && typeof label === 'string' && (label as string).trim() !== '') {
|
2019-07-31 11:12:31 +08:00
|
|
|
|
labelChildren = (label as string).replace(/[::]\s*$/, '');
|
2019-02-25 19:04:09 +08:00
|
|
|
|
}
|
|
|
|
|
|
2019-03-24 17:03:52 +08:00
|
|
|
|
const labelClassName = classNames({
|
|
|
|
|
[`${prefixCls}-item-required`]: required,
|
|
|
|
|
[`${prefixCls}-item-no-colon`]: !computedColon,
|
|
|
|
|
});
|
|
|
|
|
|
2019-02-25 19:04:09 +08:00
|
|
|
|
return label ? (
|
2019-03-04 14:51:40 +08:00
|
|
|
|
<Col {...mergedLabelCol} className={labelColClassName}>
|
2019-02-25 19:04:09 +08:00
|
|
|
|
<label
|
2019-05-06 12:04:39 +08:00
|
|
|
|
htmlFor={htmlFor || id || this.getId()}
|
2019-02-25 19:04:09 +08:00
|
|
|
|
className={labelClassName}
|
|
|
|
|
title={typeof label === 'string' ? label : ''}
|
|
|
|
|
onClick={this.onLabelClick}
|
|
|
|
|
>
|
|
|
|
|
{labelChildren}
|
|
|
|
|
</label>
|
|
|
|
|
</Col>
|
|
|
|
|
) : null;
|
|
|
|
|
}}
|
|
|
|
|
</FormContext.Consumer>
|
|
|
|
|
);
|
2015-10-09 13:53:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-05 19:12:18 +08:00
|
|
|
|
renderChildren(prefixCls: string) {
|
2017-09-27 22:32:49 +08:00
|
|
|
|
const { children } = this.props;
|
2015-10-09 13:53:04 +08:00
|
|
|
|
return [
|
2018-12-05 19:12:18 +08:00
|
|
|
|
this.renderLabel(prefixCls),
|
2015-10-09 13:53:04 +08:00
|
|
|
|
this.renderWrapper(
|
2018-12-05 19:12:18 +08:00
|
|
|
|
prefixCls,
|
2015-10-09 13:53:04 +08:00
|
|
|
|
this.renderValidateWrapper(
|
2018-12-05 19:12:18 +08:00
|
|
|
|
prefixCls,
|
2016-01-21 16:23:35 +08:00
|
|
|
|
children,
|
2018-12-05 19:12:18 +08:00
|
|
|
|
this.renderHelp(prefixCls),
|
|
|
|
|
this.renderExtra(prefixCls),
|
2017-03-23 21:15:49 +08:00
|
|
|
|
),
|
2015-10-09 13:53:04 +08:00
|
|
|
|
),
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-05 19:12:18 +08:00
|
|
|
|
renderFormItem = ({ getPrefixCls }: ConfigConsumerProps) => {
|
2019-11-06 23:30:41 +08:00
|
|
|
|
const { prefixCls: customizePrefixCls, style, className, ...restProps } = this.props;
|
2019-03-24 17:03:52 +08:00
|
|
|
|
const prefixCls = getPrefixCls('form', customizePrefixCls);
|
|
|
|
|
const children = this.renderChildren(prefixCls);
|
|
|
|
|
const itemClassName = {
|
|
|
|
|
[`${prefixCls}-item`]: true,
|
|
|
|
|
[`${prefixCls}-item-with-help`]: this.helpShow,
|
|
|
|
|
[`${className}`]: !!className,
|
|
|
|
|
};
|
2019-03-08 11:25:37 +08:00
|
|
|
|
|
2019-03-24 17:03:52 +08:00
|
|
|
|
return (
|
2019-11-06 23:30:41 +08:00
|
|
|
|
<Row
|
|
|
|
|
className={classNames(itemClassName)}
|
|
|
|
|
style={style}
|
|
|
|
|
{...omit(restProps, [
|
|
|
|
|
'id', // It is deprecated because `htmlFor` is its replacement.
|
|
|
|
|
'htmlFor',
|
|
|
|
|
'label',
|
|
|
|
|
'labelAlign',
|
|
|
|
|
'labelCol',
|
|
|
|
|
'wrapperCol',
|
|
|
|
|
'help',
|
|
|
|
|
'extra',
|
|
|
|
|
'validateStatus',
|
|
|
|
|
'hasFeedback',
|
|
|
|
|
'required',
|
|
|
|
|
'colon',
|
|
|
|
|
])}
|
|
|
|
|
key="row"
|
|
|
|
|
>
|
2019-03-24 17:03:52 +08:00
|
|
|
|
{children}
|
|
|
|
|
</Row>
|
2015-10-09 13:53:04 +08:00
|
|
|
|
);
|
2018-12-07 20:02:01 +08:00
|
|
|
|
};
|
2015-10-09 13:53:04 +08:00
|
|
|
|
|
|
|
|
|
render() {
|
2018-12-07 20:02:01 +08:00
|
|
|
|
return <ConfigConsumer>{this.renderFormItem}</ConfigConsumer>;
|
2015-10-09 13:53:04 +08:00
|
|
|
|
}
|
|
|
|
|
}
|