qm-ui
Version:
千米公有云管理端UI基础组件库
197 lines (182 loc) • 5.41 kB
JavaScript
/**
* @file
* @author gcy[of1518]
* @date 16/10/11
*
* @description Form_Element
*/
import React, { Component } from 'react'
import classNames from 'classnames'
import { Row, Col } from 'antd'
import { splitObject } from '../_util/ObjectUtil'
const noop = () => undefined
export default class ElementUI extends Component {
static defaultProps = {
id: '',
index: '', //子元素唯一标识
value: undefined, //
rules: {}, //校验规则
extra: undefined, //额外数据缓存,解决复杂表单数据的数据缓存问题
status: '', //校验状态 'success', 'warning', 'error', 'validating'
formState: '', //'' || 'view', 默认&&编辑状态,查看审核状态
viewRender: undefined, //
msg: '', //提示信息,如不设置,则会根据校验规则自动生成 string
help: '', //帮助信息
label: '', //label 标签的文本
labelCol: { span: 3, offset: 12 }, //label 标签布局,通 <Col> 组件,设置 span offset 值
wrapperCol: undefined, //需要为输入控件设置布局样式时,使用该属性
prefixCls: 'ant-form',
hasFeedback: false, //是否需要反馈
colon: false,
convertValue: undefined, //store:->value
formatValue: undefined, //onChange数据装包 默认为Event
onValid: noop,
onChange: undefined, //外部
}
constructor(props) {
super(props)
}
render() {
let { prefixCls, style, className, colon, label, value, formState, viewRender } = this.props
let children = null
switch (formState) {
case 'view':
if (viewRender && typeof viewRender === 'function') {
children = viewRender({ value, formState }) || null
break
} else if (viewRender && React.isValidElement(viewRender)) {
children = React.cloneElement(viewRender, { value, formState }) || null
break
}
default:
children = this.renderChildren()
break
}
const babel = this.renderLabel()
const itemClassName = classNames({
['ant-row-label-no']: !label,
[`${prefixCls}-item`]: true,
[`${prefixCls}-item-with-help`]: !!this.getMsg(),
[`${prefixCls}-item-no-colon`]: !colon && !babel,
[`${className}`]: !!className,
})
let [props] = splitObject(this.props, ['id', 'style'])
return (
<Row className={itemClassName} {...props}>
{babel}
{children}
</Row>
)
}
//render
renderChildren() {
let {
children,
index,
value,
rules,
hasFeedback,
prefixCls,
wrapperCol,
status,
formatValue,
onValid,
onChange,
convertValue,
} = this.props
let childrenNode = React.Children.map(children, (child, k) => {
let props = {
value: typeof convertValue === 'function' ? convertValue(value) : value,
onBlur: (data, extra) => {
if (child.props.onBlur && typeof child.props.onBlur == 'function') {
child.props.onBlur(data, extra)
}
if (rules && rules['asyncNet']) {
onValid({ index })
}
},
onChange: (data, extra) => {
if (child.props.onChange && typeof child.props.onChange == 'function') {
child.props.onChange(data, extra)
}
let value = data
if (typeof formatValue === 'function') {
value = formatValue(data)
}
value = value && value.target ? value.target.value : value
return onChange({ index, value, extra })
},
}
return React.cloneElement(child, props)
})
let classes = classNames({
'has-feedback': hasFeedback,
'has-success': status === 'success',
'has-warning': status === 'warning',
'has-error': status === 'error',
'is-validating': status === 'validating',
})
return (
<Col {...wrapperCol} key="wrapper">
<div className={`${prefixCls}-item-control ${classes}`}>
{childrenNode}
{this.renderMsg()}
{this.renderHelp()}
</div>
</Col>
)
}
/**
* label渲染
*/
renderLabel() {
let { id, label, labelCol, prefixCls, rules } = this.props
let { required } = rules || {}
const className = classNames({
[`${prefixCls}-item-required`]: !!required,
})
// remove user input colon
if (typeof label === 'string' && label.trim() !== '') {
label = label.replace(/[:|:]\s*$/, '')
}
const child = this.props.children !== undefined ? this.props.children : null
return (
<Col {...labelCol} key="label" className={`${prefixCls}-item-label`}>
<label htmlFor={id || (child && child.props && child.props['id'])} className={className}>
{label}
</label>
</Col>
)
}
/**
* 提示信息渲染
*/
renderMsg() {
const { prefixCls } = this.props
const msg = this.getMsg()
return msg ? (
<div className={`${prefixCls}-explain`} key="msg">
{msg}
</div>
) : null
}
/**
* 获取提示文本
*/
getMsg() {
return this.props.msg || null
}
/**
* 获取额外提示信息
*/
renderHelp() {
const { help } = this.props
return help ? (
typeof help == 'string' ? (
<span className="inline-tips">{help}</span>
) : (
help
)
) : null
}
}