hc-components
Version:
基于react的通用组件库
227 lines (206 loc) • 6.67 kB
JSX
import React from 'react';
import PropTypes from 'prop-types';
import Form from 'antd/lib/form';
import Row from 'antd/lib/row';
import Col from 'antd/lib/col';
import Icon from 'antd/lib/icon';
import {CustomForm} from '../customForm';
import Divider from 'material-ui/Divider';
import './index.less';
class IArchive extends React.PureComponent {
static propTypes = {
options: PropTypes.array,
dataSource: PropTypes.object,
limit: PropTypes.number,
form: PropTypes.object,
cols: PropTypes.number,
readonly: PropTypes.bool,
compact: PropTypes.bool,
layout: PropTypes.string,
formItemLayout: PropTypes.object,
onChange: PropTypes.func,
onSubmit: PropTypes.func,
formatter: PropTypes.func,
noLabel: PropTypes.bool,
style: PropTypes.object,
className: PropTypes.string,
buttons: PropTypes.array,
buttonProps: PropTypes.object
}
static defaultProps = {
options: [],
dataSource: {},
cols: 3,
readonly: true,
compact: false,
buttonProps: {noButton: true},
className: '',
style: {}
}
constructor(props, context) {
super(props, context);
this.state = {
expand: !props.limit || props.limit > props.options.length,
dataSource: this.props.dataSource
};
}
componentWillReceiveProps(nextProps) {
if (nextProps.dataSource !== this.props.dataSource) {
this.setState({dataSource: nextProps.dataSource});
}
}
getFieldValue(name, option, editable) {
let value;
if (this.state.dataSource[name] === undefined) {
value = option.value;
} else {
value = this.state.dataSource[name];
}
if (this.props.formatter) {
return this.props.formatter(value, option);
} else {
if (editable) {
return option.renderInput ? option.renderInput(value, this.state.dataSource) : value;
} else {
return option.render ? option.render(value, this.state.dataSource) : value;
}
}
}
getFieldInput(name, option) {
const {form, readonly, onChange} = this.props;
const editable = option.editable === undefined ? !readonly : option.editable;
if (editable) {
/**
* option = {
* dataType | type,
* enum,
* options,
* format,
* mode,
* dragger,
* action,
* valuePropName,
* Component,
* max,
* maxLength,
* maximum,
* disabled,
* placeholder
* }
*/
const decorator = option.decorator || {};
if (onChange) {
decorator.getValueFromEvent = (e) => {
const v = CustomForm.getValueFromEvent(e, option);
onChange(v, name);
return v;
};
}
decorator.defaultValue = this.getFieldValue(name, option, editable);
const stateProps = option.getProps && option.getProps.call(this, this.props, this.state.dataSource, (nextState) => {
this.setState({
dataSource: Object.assign({}, this.state.dataSource, nextState)
});
}, this.props.form);
if (stateProps === false) return null;
const fieldInput = CustomForm.getFieldInput(option, option.props, stateProps || {}, decorator);
return form.getFieldDecorator(name, decorator)(fieldInput);
} else {
return this.getFieldValue(name, option);
}
}
getFields() {
const {options, limit, cols, formItemLayout, compact, noLabel} = this.props;
const span = Math.floor(24 / cols);
const count = this.state.expand ? options.length : limit;
// const {getFieldDecorator} = form;
const fields = [];
const itemStyle = compact ? {marginBottom: 0} : {};
let item;
let name;
let label;
let input;
for (let i = 0; i < count; i++) {
item = options[i];
if (item && (item.dataIndex || item.name)) {
name = item.dataIndex || item.name;
label = noLabel ? null : (item.title || item.name);
input = this.getFieldInput(name, item);
if (input) {
fields.push(
<Col span={item.col ? item.col * span : item.span || span} key={name} style={{display: i < count ? 'block' : 'none'}}>
<Form.Item {...formItemLayout} {...item.attrs} label={label} style={itemStyle}>
{input}
</Form.Item>
</Col>
);
}
}
}
return fields;
}
toggle = () => {
this.setState({expand: !this.state.expand});
}
handleSubmit = (e) => {
e && e.preventDefault();
this.props.form.validateFields((err, values) => {
if (!err) {
this.props.options.forEach(option => {
if (option.getValue) {
const name = option.dataIndex || option.name;
values[name] = option.getValue(values[name]);
}
});
this.props.onSubmit && this.props.onSubmit(values);
}
});
}
getButtons() {
const {buttons, buttonProps} = this.props;
if (buttonProps.onSubmit) {
buttonProps.onSubmit.bind(this.state.dataSource);
} else {
buttonProps.onSubmit = this.handleSubmit;
}
const justify = buttonProps.align || 'end';
const _buttons = CustomForm.getButtons(buttons, buttonProps);
return _buttons ? (<Row justify={justify} type="flex" className="o-com-archive_btns" style={buttonProps.btnStyle}>{_buttons}</Row>) : null;
}
render() {
return (<Form className={'o-com-archive ' + this.props.className} style={this.props.style} layout={this.props.layout} onSubmit={this.props.buttonProps.noButton && this.handleSubmit}>
<Row gutter={24}>
{this.getFields()}
{this.props.limit && this.props.limit < this.props.options.length ? (<a className="o-com-archive_expand" onClick={this.toggle}>
more <Icon type={this.state.expand ? 'up' : 'down'} />
</a>) : null}
</Row>
{this.getButtons()}
</Form>);
}
}
class ArchiveGroup extends React.PureComponent {
static propTypes = {
options: PropTypes.array,
dataSource: PropTypes.object
}
static defaultProps = {
options: [],
dataSource: {}
}
render() {
return (<div className="o-com-archive-group">
{
this.props.options.map(item => {
return (<div key={item.name} className="o-com-archive-group_box">
<h5>{item.title || item.name}</h5>
<Divider />
<Archive {...item.attrs} {...this.props} options={item.items} dataSource={this.props.dataSource[item.name]} />
</div>);
})
}
</div>);
}
}
export const Archive = Form.create({name: 'archive'})(IArchive);
Archive.Group = ArchiveGroup;