|
|
|
import React from 'react';
|
|
|
|
import classNames from 'classnames';
|
|
|
|
import PureRenderMixin from 'rc-util/lib/PureRenderMixin';
|
|
|
|
import Row from '../row';
|
|
|
|
import Col from '../col';
|
|
|
|
import { WrappedFormUtils } from './Form';
|
|
|
|
import { FIELD_META_PROP } from './constants';
|
|
|
|
import warning from '../_util/warning';
|
|
|
|
|
|
|
|
export interface FormItemLabelColOption {
|
|
|
|
span: number;
|
|
|
|
offset?: number;
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface FormItemProps {
|
|
|
|
prefixCls?: string;
|
|
|
|
id?: string;
|
|
|
|
label?: React.ReactNode;
|
|
|
|
labelCol?: FormItemLabelColOption;
|
|
|
|
wrapperCol?: FormItemLabelColOption;
|
|
|
|
help?: React.ReactNode;
|
|
|
|
extra?: string;
|
|
|
|
validateStatus?: 'success' | 'warning' | 'error' | 'validating';
|
|
|
|
hasFeedback?: boolean;
|
|
|
|
className?: string;
|
|
|
|
required?: boolean;
|
|
|
|
style?: React.CSSProperties;
|
|
|
|
colon?: boolean;
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface FormItemContext {
|
|
|
|
form: WrappedFormUtils;
|
|
|
|
vertical: boolean;
|
|
|
|
}
|
|
|
|
|
|
|
|
export default class FormItem extends React.Component<FormItemProps, any> {
|
|
|
|
static defaultProps = {
|
|
|
|
hasFeedback: false,
|
|
|
|
prefixCls: 'ant-form',
|
|
|
|
colon: true,
|
|
|
|
};
|
|
|
|
|
|
|
|
static propTypes = {
|
|
|
|
prefixCls: React.PropTypes.string,
|
|
|
|
label: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.node]),
|
|
|
|
labelCol: React.PropTypes.object,
|
|
|
|
help: React.PropTypes.oneOfType([React.PropTypes.node, React.PropTypes.bool]),
|
|
|
|
validateStatus: React.PropTypes.oneOf(['', 'success', 'warning', 'error', 'validating']),
|
|
|
|
hasFeedback: React.PropTypes.bool,
|
|
|
|
wrapperCol: React.PropTypes.object,
|
|
|
|
className: React.PropTypes.string,
|
|
|
|
id: React.PropTypes.string,
|
|
|
|
children: React.PropTypes.node,
|
|
|
|
colon: React.PropTypes.bool,
|
|
|
|
};
|
|
|
|
|
|
|
|
static contextTypes = {
|
|
|
|
form: React.PropTypes.object,
|
|
|
|
vertical: React.PropTypes.bool,
|
|
|
|
};
|
|
|
|
|
|
|
|
context: FormItemContext;
|
|
|
|
|
|
|
|
componentDidMount() {
|
|
|
|
warning(
|
|
|
|
this.getControls(this.props.children, true).length <= 1,
|
|
|
|
'`Form.Item` cannot generate `validateStatus` and `help` automatically, ' +
|
|
|
|
'while there are more than one `getFieldDecorator` in it.'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
shouldComponentUpdate(...args) {
|
|
|
|
return PureRenderMixin.shouldComponentUpdate.apply(this, args);
|
|
|
|
}
|
|
|
|
|
|
|
|
getHelpMsg() {
|
|
|
|
const context = this.context;
|
|
|
|
const props = this.props;
|
|
|
|
if (props.help === undefined && context.form) {
|
|
|
|
return this.getId() ? (context.form.getFieldError(this.getId()) || []).join(', ') : '';
|
|
|
|
}
|
|
|
|
|
|
|
|
return props.help;
|
|
|
|
}
|
|
|
|
|
|
|
|
getControls(children, recursively: boolean) {
|
|
|
|
let controls: React.ReactElement<any>[] = [];
|
|
|
|
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>;
|
|
|
|
if (child.type as any === FormItem) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!child.props) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (FIELD_META_PROP in child.props) {
|
|
|
|
controls.push(child);
|
|
|
|
} else if (child.props.children) {
|
|
|
|
controls = controls.concat(this.getControls(child.props.children, recursively));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return controls;
|
|
|
|
}
|
|
|
|
|
|
|
|
getOnlyControl() {
|
|
|
|
const child = this.getControls(this.props.children, false)[0];
|
|
|
|
return child !== undefined ? child : null;
|
|
|
|
}
|
|
|
|
|
|
|
|
getChildProp(prop) {
|
|
|
|
const child = this.getOnlyControl() as React.ReactElement<any>;
|
|
|
|
return child && child.props && child.props[prop];
|
|
|
|
}
|
|
|
|
|
|
|
|
getId() {
|
|
|
|
return this.getChildProp( |