ant-design/components/form/FormItem.jsx

214 lines
5.3 KiB
React
Raw Normal View History

2015-10-09 13:53:04 +08:00
import React from 'react';
import classNames from 'classnames';
2015-10-09 13:53:04 +08:00
function prefixClsFn(prefixCls, ...args) {
return args.map((s) => `${prefixCls}-${s}`).join(' ');
2015-10-09 13:53:04 +08:00
}
export default class FormItem extends React.Component {
static defaultProps = {
hasFeedback: false,
prefixCls: 'ant-form',
}
static propTypes = {
prefixCls: React.PropTypes.string,
label: 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,
}
static contextTypes = {
form: React.PropTypes.object,
}
getLayoutClass(colDef) {
if (!colDef) {
return '';
}
2016-01-05 14:42:06 +08:00
const { span, offset } = colDef;
const col = span ? `col-${span}` : '';
const offsetCol = offset ? ` col-offset-${offset}` : '';
return col + offsetCol;
}
2016-01-21 16:23:35 +08:00
getHelpMsg() {
const context = this.context;
const props = this.props;
if (props.help === undefined && context.form) {
return this.getId() ? (context.form.getFieldError(this.getId()) || []).join(', ') : '';
2016-01-21 16:23:35 +08:00
}
return props.help;
}
getOnlyControl() {
const children = React.Children.toArray(this.props.children);
const child = children.filter((c) => {
return c.props && '__meta' in c.props;
})[0];
return child !== undefined ? child : null;
}
getChildProp(prop) {
const child = this.getOnlyControl();
return child && child.props && child.props[prop];
}
2016-01-28 21:43:45 +08:00
getId() {
return this.getChildProp('id');
2016-01-28 21:43:45 +08:00
}
2016-02-01 10:23:06 +08:00
getMeta() {
return this.getChildProp('__meta');
2016-02-01 10:23:06 +08:00
}
2015-10-09 13:53:04 +08:00
renderHelp() {
2016-01-21 16:23:35 +08:00
const props = this.props;
const prefixCls = props.prefixCls;
const help = this.getHelpMsg();
2016-04-12 14:55:02 +08:00
return help ? (
2016-04-25 16:27:47 +08:00
<div className={prefixClsFn(prefixCls, 'explain')} key="help">
2016-04-12 14:55:02 +08:00
{help}
2015-10-09 13:53:04 +08:00
</div>
2016-04-12 14:55:02 +08:00
) : null;
2015-10-09 13:53:04 +08:00
}
2016-04-25 16:25:57 +08:00
renderExtra() {
const { prefixCls, extra } = this.props;
return extra ? (
<span className={prefixClsFn(prefixCls, 'extra')}>{extra}</span>
) : null;
2016-04-25 16:25:57 +08:00
}
2016-01-21 16:23:35 +08:00
getValidateStatus() {
const { isFieldValidating, getFieldError, getFieldValue } = this.context.form;
2016-01-28 21:43:45 +08:00
const field = this.getId();
if (!field) {
return '';
}
2016-01-21 16:23:35 +08:00
if (isFieldValidating(field)) {
return 'validating';
} else if (!!getFieldError(field)) {
return 'error';
2016-01-25 15:00:03 +08:00
} else if (getFieldValue(field) !== undefined) {
2016-01-21 16:23:35 +08:00
return 'success';
}
return '';
2016-01-21 16:23:35 +08:00
}
2016-01-26 15:40:47 +08:00
renderValidateWrapper(c1, c2, c3) {
let classes = '';
2016-01-21 16:23:35 +08:00
const form = this.context.form;
const props = this.props;
const validateStatus = (props.validateStatus === undefined && form) ?
2016-01-28 21:43:45 +08:00
this.getValidateStatus() :
props.validateStatus;
2016-01-21 16:23:35 +08:00
if (validateStatus) {
classes = classNames(
2015-10-09 13:53:04 +08:00
{
2016-01-21 16:23:35 +08:00
'has-feedback': props.hasFeedback,
'has-success': validateStatus === 'success',
'has-warning': validateStatus === 'warning',
'has-error': validateStatus === 'error',
'is-validating': validateStatus === 'validating',
2015-10-09 13:53:04 +08:00
}
);
}
return (
<div className={`${this.props.prefixCls}-item-control ${classes}`}>
2016-01-26 15:38:58 +08:00
{c1}{c2}{c3}
</div>
);
2015-10-09 13:53:04 +08:00
}
renderWrapper(children) {
const wrapperCol = this.props.wrapperCol;
return (
<div className={this.getLayoutClass(wrapperCol)} key="wrapper">
2015-10-09 13:53:04 +08:00
{children}
</div>
);
2015-10-09 13:53:04 +08:00
}
2016-01-21 16:23:35 +08:00
isRequired() {
2016-01-28 21:43:45 +08:00
if (this.context.form) {
2016-02-01 10:23:06 +08:00
const meta = this.getMeta() || {};
const validate = (meta.validate || []);
return validate.filter((item) => !!item.rules).some((item) => {
2016-01-28 21:43:45 +08:00
return item.rules.some((rule) => rule.required);
});
}
return false;
2016-01-21 16:23:35 +08:00
}
2015-10-09 13:53:04 +08:00
renderLabel() {
2016-01-21 16:23:35 +08:00
const props = this.props;
const labelCol = props.labelCol;
const required = props.required === undefined ?
2016-01-28 21:43:45 +08:00
this.isRequired() :
props.required;
2015-10-09 13:53:04 +08:00
const className = classNames({
[this.getLayoutClass(labelCol)]: true,
2016-02-03 14:00:38 +08:00
[`${props.prefixCls}-item-required`]: required,
});
2016-01-21 16:23:35 +08:00
return props.label ? (
<label htmlFor={props.id || this.getId()} className={className} key="label">
2016-01-21 16:23:35 +08:00
{props.label}
2015-10-09 13:53:04 +08:00
</label>
2015-11-03 13:50:36 +08:00
) : null;
2015-10-09 13:53:04 +08:00
}
renderChildren() {
2016-01-21 16:23:35 +08:00
const props = this.props;
2016-01-28 21:43:45 +08:00
const children = React.Children.map(props.children, (child) => {
2016-03-01 17:52:07 +08:00
if (child && typeof child.type === 'function' && !child.props.size) {
2016-02-01 10:23:06 +08:00
return React.cloneElement(child, { size: 'large' });
}
2016-02-01 10:23:06 +08:00
return child;
2016-01-28 21:43:45 +08:00
});
2015-10-09 13:53:04 +08:00
return [
this.renderLabel(),
this.renderWrapper(
this.renderValidateWrapper(
2016-01-21 16:23:35 +08:00
children,
2016-01-26 15:38:58 +08:00
this.renderHelp(),
2016-04-25 16:31:32 +08:00
this.renderExtra()
2015-10-09 13:53:04 +08:00
)
),
];
}
renderFormItem(children) {
const props = this.props;
const prefixCls = props.prefixCls;
const style = props.style;
2015-10-09 13:53:04 +08:00
const itemClassName = {
[`${prefixCls}-item`]: true,
[`${prefixCls}-item-with-help`]: !!this.getHelpMsg(),
2016-01-12 14:24:42 +08:00
[`${props.className}`]: !!props.className,
2015-10-09 13:53:04 +08:00
};
return (
<div className={classNames(itemClassName)} style={style}>
2015-10-09 13:53:04 +08:00
{children}
</div>
);
}
render() {
const children = this.renderChildren();
return this.renderFormItem(children);
}
}