基于Antd的表单封装

antd表单封装插件

表单可基于antd二次封装(优势:减少代码量,统一管理表单配置,跨组件使用antd的form对象)

import React, {Component} from 'react';
import {
  Form,
  Row,
  Col,
  Input,
  Button,
  Icon,
  DatePicker,
  Select,
  Switch,
  InputNumber,
  Upload,
  Cascader
} from 'antd';
import PropsTypes from 'prop-types';
import provinces from "china-division/dist/provinces.json";
import cities from "china-division/dist/cities.json";
import areas from "china-division/dist/areas.json";


//省市区
areas.forEach(area => {
  const matchCity = cities.filter(city => city.code === area.cityCode)[0];
  if (matchCity) {
    matchCity.children = matchCity.children || [];
    matchCity.children.push({
      label: area.name,
      value: area.name
    });
  }
});


cities.forEach(city => {
  const matchProvince = provinces.filter(
    province => province.code === city.provinceCode
  )[0];
  if (matchProvince) {
    matchProvince.children = matchProvince.children || [];
    matchProvince.children.push({
      label: city.name,
      value: city.name,
      children: city.children
    });
  }
});


const options = provinces.map(province => ({
  label: province.name,
  value: province.name,
  children: province.children
}));


const {TextArea} = Input;
const {MonthPicker, RangePicker, WeekPicker} = DatePicker;
const Option = Select.Option;


class SearchArea extends Component {


  static propTypes = {
    filedList: PropsTypes.array.isRequired,//字段列表
    hideExpand: PropsTypes.bool,//是否隐藏收起按钮
    formItemLayout: PropsTypes.shape({}),//可以修改表单key和value的布局,具体看antd
  };


  constructor(props) {
    super(props);
    this.state = {
      expand: true,
      expandNum: 5
    };
  }


  //渲染单个字段 根据列表的type返回不同的react元素 TODO:可以在这里进行扩展
  getFiledCell = (item) => {
    switch (item.type) {
      case 'input':
        return (<Input className={'wd-170'} allowClear={true} {...item.attr} />);
      case 'RangePicker' :
        return (<RangePicker allowClear={true} {...item.attr} />);
      case 'select':
        return (
          <Select className={'wd-170_im'} allowClear={true}>
            {
              item.option.map(temIn => (
                <Option key={temIn.key} value={temIn.value}>{temIn.key}</Option>
              ))
            }
          </Select>
        );
      case 'switch' :
        return (<Switch {...item.attr} />);
      case 'number' :
        return (<InputNumber allowClear={true} {...item.attr} />);
      case 'textarea' :
        return (<TextArea allowClear={true} {...item.attr} />);
      case 'mulInput' :
        return (
          <div style={{display: 'flex'}}>
            <Input allowClear={true} {...item.attr} />
            <Input allowClear={true} {...item.attr} />
            <Input allowClear={true} {...item.attr} />
          </div>
        );
      case 'importFile' :
        return (
          <Upload {...item.attr}>
            <Button>
              <Icon type="upload"/> 点击上传
            </Button>
          </Upload>
        );
      case 'templateDownload' :
        return (
          <div>
            <a href={item.url}>{item.fileName}</a>
          </div>
        );
      case 'CascadeAddress' :
        return (
          <Cascader options={options} {...item.attr} />
        );
      default:
        return (<Input allowClear={true} {...item.attr} />);
    }
  };


  getFiledList(filedList) {
    const {expand, expandNum} = this.state;
    const {form, hideExpand} = this.props;
    return filedList.map((item, index) => {
      //const count = hideExpand ? 0 : (expand && expandNum);
      const {getFieldDecorator} = form;
      if(!item.type) {
        getFieldDecorator(item.paramName, {
          initialValue: item.initialValue
        });
        return '';
      }
      return (
        <Form.Item label={item.filedName}
                   key={index.toString()}
                   style={{ marginRight: "20px"}}>
          {getFieldDecorator(item.paramName, {
            initialValue: item.initialValue,
            rules: item.rules,
          })(
            this.getFiledCell(item),
          )}
        </Form.Item>
      );
    });
  }




  toggle = () => {
    const {expand} = this.state;
    this.setState({expand: !expand});
  };


  handleSearch = () => {


  };


  handleReset = () => {


  };
  //默认表单布局
  formItemLayout = this.props.formItemLayout || {
    labelCol: {
      xs: {span: 24},
      sm: {span: 8},
    },
    wrapperCol: {
      xs: {span: 24},
      sm: {span: 16},
    },
  };


  render() {
    const {filedList, hideExpand, onFormInit, form} = this.props;
    let {expandNum} = this.state;
    onFormInit(form);
    return (
      <div className="search-area">
        {
          <Form
            className="ant-advanced-search-form"
            onSubmit={this.handleSearch}
            {...this.formItemLayout}
          >
            <Row align="middle" type="flex" gutter={24}>
              {this.getFiledList(filedList)}
            </Row>
            {
              !hideExpand && filedList.length > expandNum && <Row>
                <Col span={24} style={{textAlign: 'right'}}>
                  <a style={{marginLeft: 8, fontSize: 12}} onClick={this.toggle}>
                    {this.state.expand ? '展开' : '收起'}
                    <Icon type={this.state.expand ? 'down' : 'up'}/>
                  </a>
                </Col>
              </Row>
            }
          </Form>
        }
      </div>
    );
  }
}


export default Form.create({
  name: 'advanced_search',
  onValuesChange: (props, value, oldVal) => {
    props.onValuesChange && typeof props.onValuesChange === 'function' && props.onValuesChange(value, props.form)
  }
})(SearchArea);

外部调用实例

filedList: [
  {
    filedName: '订单编号',
    width: 250,
    paramName: 'order_number',
    type: 'input'
  },
  {
    filedName: '订单来源',
    paramName: 'order_from',
    type: 'select',
    option: []
  },
  {
    filedName: '配货时间',
    paramName: 'pick_time',
    type: 'RangePicker',
    attr: {
      placeholder: ['开始时间', '结束时间'],
      style: {
        width: 300
      }
    }
  },
    {
    filedName: '角色名称',
    span:24,
    paramName: 'role_name',
    type: 'input',
    initialValue: '',
    rules: [
      {
        required: true,
        message: '请输入角色名称',
      },
    ]
  },
  {
    filedName: '角色状态',
    span:24,
    paramName: 'is_lock',
    type: 'switch',
    initialValue: 1
  }
],//筛选区域表单的配置

onFormInit(form) {
  //antd的form对象
  form.validateFields(()=>{})
}

<SearchArea onFormInit={this.onFormInit.bind(this)} filedList={filedList}/>
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值