【antd】根据后台数据动态生成表单和数据更新

具体需求是:

1 根据后台数据动态生成表单项

2 表单项可以编辑和增减,提交保存数据到后台

大概界面如下:

对于需求1,找了下基本通过map枚举,配合getFieldDecorator

对于需求2,如果编辑过程中,增减表单项,将造成正在编辑的表单数据丢失的情况,如下:

没找到完整的解决方案,自己摸索了下,通过onValuesChange监听所有表单改动,更新state来保存实时编辑的.

还有一个问题是,对于编辑过的表单,即使数据更新了,表单还是不会刷新(重新渲染),如在tab切换时,因为所有两个tab的key是一样的,如果在左边某个表单做了编辑,切换到右边tab时,对应的表单就不会数据变化了,如下:

下面是实现的代码:

组件加载完后去获取后台数据:

  componentDidMount() {
    const { dispatch } = this.props;
    const {activeKey} = this.state;
    dispatch({
      type: 'brokage/fetchTable',
      paylaod:{Category:activeKey},
    });
  }

render函数,根据后台数据渲染表单:


  render() {
    const limitDecimals = value => {
      const reg = /^(\-)*(\d+)\.(\d\d).*$/;

      if (typeof value === 'string') {
        return !isNaN(Number(value)) ? value.replace(reg, '$1$2.$3') : '';
      } else if (typeof value === 'number') {
        return !isNaN(value) ? String(value).replace(reg, '$1$2.$3') : '';
      } else {
        return '';
      }
    };

    const {
      brokage: { table },
      loading,
    } = this.props;

    const { getFieldDecorator } = this.props.form;

    return (
      <PageHeaderWrapper
        title="佣金设置"
        content="佣金规则最少两条,价格必须递增,最后一条规则为佣金上限"
      >
        <Form onSubmit={this.handleSubmit}>
          <Tabs defaultActiveKey="1" onChange={this.HandChangePane}>

            <TabPane
              tab={
                <span>
                  <Icon type="user" />
                  客户佣金设置
                </span>
              }
              key="1"
            >
              <Card bordered={false}>
                <div>
                  {table.data &&
                    table.data.map((element, index) => (
                      <span key={index}>
                        <Row gutter={{ xs: 8, sm: 16, md: 24, lg: 64 }}>
                          <Col span={6}>
                            <FormItem label="单价小于" {...this.formLayout}>
                              {getFieldDecorator(`price${index}`, {
                                initialValue: element.Max,
                                rules: [
                                  {
                                    required: true,
                                    message: '请输入价格,只能输入数字,小数最多两位',
                                  },
                                ],
                              })(
                                <InputNumber
                                  min={0}
                                  step={0.01}
                                  formatter={limitDecimals}
                                  parser={limitDecimals}
                                  placeholder="请输入价格上限"
                                />
                              )}
                            </FormItem>
                          </Col>
                          <Col md={5} sm={10}>
                            <FormItem label="佣金" {...this.formLayout}>
                              {getFieldDecorator(`brokage${index}`, {
                                initialValue: element.Brokerage,
                                rules: [
                                  {
                                    required: true,
                                    message: '请输入佣金,只能输入数字,小数最多两位',
                                  },
                                ],
                              })(
                                <InputNumber
                                  key={{ index }}
                                  min={0}
                                  step={0.01}
                                  size={40}
                                  formatter={limitDecimals}
                                  parser={limitDecimals}
                                  placeholder="请输入佣金"
                                />
                              )}
                            </FormItem>
                          </Col>
                          <Col md={4} sm={24}>
                            {index > table.data.length - 2 && (
                              <Button
                                shape="circle"
                                size="small"
                                icon="plus"
                                type="primary"
                                onClick={() => this.addTag()}
                              />
                            )}
                            {index > 1 && (
                              <Button
                                shape="circle"
                                size="small"
                                icon="minus"
                                type="default"
                                onClick={() => this.removeTag(index)}
                              />
                            )}
                          </Col>
                        </Row>
                      </span>
                    ))}
                </div>
              </Card>
            </TabPane>
            <TabPane
              tab={
                <span>
                  <Icon type="shop" />
                  商家佣金设置
                </span>
              }
              key="2"
            >
              <Card bordered={false}>
                <div>

                  {table.data &&
                  table.data.map((element, index) => (
                    <span key={index}>
                        <Row gutter={{ xs: 8, sm: 16, md: 24, lg: 64 }}>
                          <Col span={6}>
                            <FormItem label="单价小于" {...this.formLayout}>
                              {getFieldDecorator(`price${index}`, {
                                initialValue: element.Max,
                                rules: [
                                  {
                                    required: true,
                                    message: '请输入价格,只能输入数字,小数最多两位',
                                  },
                                ],
                              })(
                                <InputNumber
                                  // disabled={index != table.data.length - 1 ? false : true}
                                  min={0}
                                  step={0.01}
                                  formatter={limitDecimals}
                                  parser={limitDecimals}
                                  placeholder="请输入价格上限"
                                />
                              )}
                            </FormItem>
                          </Col>
                          <Col md={5} sm={10}>
                            <FormItem label="佣金" {...this.formLayout}>
                              {getFieldDecorator(`brokage${index}`, {
                                initialValue: element.Brokerage,
                                rules: [
                                  {
                                    required: true,
                                    message: '请输入佣金,只能输入数字,小数最多两位',
                                  },
                                ],
                              })(
                                <InputNumber
                                  key={{ index }}
                                  min={0}
                                  step={0.01}
                                  size={40}
                                  formatter={limitDecimals}
                                  parser={limitDecimals}
                                  placeholder="请输入佣金"
                                />
                              )}
                            </FormItem>
                          </Col>
                          <Col md={4} sm={24}>
                            {index > table.data.length - 2 && (
                              <Button
                                shape="circle"
                                size="small"
                                icon="plus"
                                type="primary"
                                onClick={() => this.addTag()}
                              />
                            )}
                            {index > 1 && (
                              <Button
                                shape="circle"
                                size="small"
                                icon="minus"
                                type="default"
                                onClick={() => this.removeTag(index)}
                              />
                            )}
                          </Col>
                        </Row>
                      </span>
                  ))}
                </div>
              </Card>
            </TabPane>
          </Tabs>
          <div style={{ overflow: 'hidden' }}>
            <div style={{ float: 'left', marginBottom: 24 }}>
              <Button type="primary" htmlType="submit" >
                保存
              </Button>
            </div>
          </div>
        </Form>
      </PageHeaderWrapper>
    );

添加表单项处理:

  addTag() {
    const { dispatch, brokage } = this.props;

    let data = brokage.table.data || [];
    let count = brokage.table.count || 0;

    data = data.concat({ Brokerage: 0, Max: 0 });
    count = count + 1;

    dispatch({
      type: 'brokage/updateTable',
      payload: { data: data, count: count },
    });
  }

对应model处理是,其实就是在table的data末尾附加新元素,触发表单重新渲染:

  effects: {
    *updateTable({ payload }, { select, call, put }) {
      yield put({
        type: 'update',
        payload: payload,
      });
    },


....
  reducers: {

    update(state, action) {
      if (action.payload.count === 0 || !action.payload.data) {
        let data = [];
        data = data.concat({ Brokerage: 0, Max: 0 }, { Brokerage: 0, Max: 0 });

        return {
          ...state,
          table: { data: data, count: 2 },
        };
      }
      return {
        ...state,
        table: action.payload,
      };
    },
....

删除表单项处理:

 removeTag(index) {
    const { dispatch, brokage } = this.props;
    let data = brokage.table.data;
    let count = brokage.table.count;

    if (count === 0 || data.length === 0) {
      return;
    }
    // can use data-binding to set
    data.splice(index, 1);
    count = count - 1;
    dispatch({
      type: 'brokage/updateTable',
      payload: { data: data, count: count },
    });

  }

对应model处理,和添加表单项处理是一样的。

数据编辑实时更新到state,这里比较粗暴,把表单项数据枚举一遍,赋值的state:

@Form.create({
  onValuesChange(props, changedValues, allValues) {
    // 表单项变化时请求数据
    const { dispatch, brokage } = props;
    let data = [];
    let count = brokage.table.count;
    for (let i = 0; i < count; i++) {
      data = data.concat({ Brokerage: allValues[`brokage${i}`], Max: allValues[`price${i}`] });
    }
    // 更新state
    dispatch({
      type: 'brokage/updateTable',
      payload: { data: data, count: count },
    });
  },
})

还有一个就是,表单项编辑后,切换tab,后台数据更新,表单项也也不更新问题,只需reset一下表单就行了:

  HandChangePane(key){
    const { dispatch } = this.props;
    //重置表单
   this.props.form.resetFields();
    let activeKey=0;
    if(key=="1"){
      activeKey=0;
    }else{
      activeKey=1;
    }
    this.setState({activeKey:activeKey});
    
    setTimeout(function(){
    dispatch({
      type: 'brokage/fetchTable',
      payload:{Category:activeKey},
    });
    },10);

  }

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值