react + antd 动态表单

1,813 阅读1分钟
需要实现动态表单的增删以及对应id下的二级分类
  1. 首先删除,利用antd本身提供的方法,使用key值即可实现。
  2. 其次添加,定义全局当前key值,在key的基础上进行新增,同样利用antd本身的方法(校验当前输入是否为空)
  3. 最后因为需求,所以在搜索时出现当前对应的id单位,要考虑重复的、单位分类为空的禁止添加,下面是实现的过程。
  4. 需要注意添加新的表单或是修改某个表单要注意位置,this.state中的数据要更改
//首先是页面部分(this.state的定义就不写啦)
render() {
     const {form: { getFieldDecorator, getFieldValue}} = this.props;
     getFieldDecorator('keys', { initialValue: this.state.defaultLeval.keyArr ? this.state.defaultLeval.keyArr : [] });
     const keys = getFieldValue('keys'); 

     const formItems = keys.length && keys.map((k, index) => (
          <div>
            <Form.Item label='ID' required={true} key={k} >
              {getFieldDecorator(`releateAucrs[${k}]`, {
                validateTrigger: ['onChange', 'onBlur'],
                rules: [{ required: true,whitespace: true,message: `请输入ID`}],
                initialValue: this.state.defaultLeval.typeName[k]
              })(<Search placeholder={`请输入ID`} style={{ width: '180px', marginRight: 8 }} onSearch={(e) => this.changeId(e, k, 1)} enterButton />)}
              <span>{this.state.companyArr[k] ? this.state.companyArr[k].aucrName : ''}</span>
              {
                  keys.length > 1 ? 
                  (<Icon style={{ color: 'red', fontSize: 20, marginRight: 10, }} className="dynamic-delete-button" type="minus-circle-o" onClick={() => this.remove(k, 'keys')}/>) : null} //当表单条数大于1时才允许删除

              {
                  index == keys.length - 1 ? 
                  (<Icon type="plus-circle" style={{ color: 'green', fontSize: 20 }} onClick={() => this.add(k, 'keys')} />) : null}
            </Form.Item>
            {
              this.state.companyArr[k] && this.state.companyArr[k].itemCate1s ? <Form.Item label='选择分类'>
                {
                  getFieldDecorator(`releateCategorys[${k}]`, {
                    initialValue: this.state.companyArr[k].initArr.length?this.state.companyArr[k].initArr:this.state.companyArr[k].itemCate1s,
                    rules: [{ required: true, message: '请选择分类' }],
                  })(
                    this.state.companyArr[k].itemCate1s.length ? 
                    <Select
                      onChange={this.testSelect}
                      mode="multiple"
                      style={{ width: 400 }}
                      placeholder="请选择分类"
                      labelInValue
                      notFoundContent={'暂无可选分类'}
                    >
                      {
                        this.state.companyArr[k].itemCate1s.map((opt, i) => {
                          return (
                            <Option key={i + 'opt'} value={opt.key}>{opt.label}</Option>
                          )
                        })
                      }

                    </Select> : <div>暂无可选分类,请切换ID</div>
                  )
                }
              </Form.Item> : ''
            }

          </div>

    ));
    return(
        <Form>
            {formItems}
        </Form>
    )
}

//删除
remove = (k, str) => {
    const { form } = this.props;
    const keys = form.getFieldValue(str);
    if (keys.length === 1) {
      return;
    }
    form.setFieldsValue({
      [str]: keys.filter(key => key !== k),
    })
};


//添加
add = (k, str) => {
    const { form } = this.props;
    const keys = form.getFieldValue(str);
    this.props.form.validateFields(['keys'],(err, values) => {
      if (!err) {
          let nextKeys = []
          if (str == 'keys') {
            nextKeys = keys.concat(this.state.id++);
          } 
          form.setFieldsValue({
            [str]: nextKeys,
          });
      }else{
        return
      }
   });
};

//根据ID获取信息及分类
changeId = (e, k, n, initArr) => {//e为目标值,k为当前key值,n区分编辑或者删除,initArr初始分类数组
    let targetVal = e
    var targetArr = form.getFieldValue('releateAucrs')
    var newTag = []
    for(var i=0;i<targetArr.length;i++){   //编辑时一些表单为undefined,所以循环判断了,并去重
        if(targetArr[i]){
          if(!newTag.includes(targetArr[i])){
            newTag.push(targetArr[i])
          }
        }else{
          newTag.push(targetArr[i])
        }
    }
    if(targetArr.length!=newTag.length){  //判断去重后的长度与当前表单长度是否一致
      message.error('已关联该id,请勿重复添加')
      return
    }
  
    dispatch({
      type: url,//这里为获取信息接口
      params: {
        aucrId: e
      },
      callback: (res) => {
        if (res.statusCode == 200) {
          let { companyArr } = this.state;
          let { aucrId, itemCate1s, aucrName, aucrLogo } = res.result

          if (itemCate1s && itemCate1s.length > 0) {
            let flarr = []
            let initArrs = []

            itemCate1s.forEach((_)=> {//新增时新的分类
              flarr.push({ key: _.itemCate1Id, label: _.itemCate1Name })
            })

            if(initArr && initArr.length){//编辑时默认的分类
              initArr.forEach((_)=>{
                initArrs.push({ key: _.itemCate1Id, label: _.itemCate1Name }) 
              })
            }
            
            var newcomArr = []
            for(var i=0;i<targetArr.length;i++){
              if(typeof(targetArr[i])=='undefined'){
                newcomArr.push({aucrName:'无',aucrId:i})
              }else{
                newcomArr.push(companyArr[i]?companyArr[i]:[])
              }
            }
          
            let obj = {}
            var newObj = {
              aucrName: aucrName,
              aucrId: aucrId,
              aucrLogo: aucrLogo,
              itemCate1s: flarr,
              initArr: n==2?initArrs:[]
            }
            var arr = []
            if(newcomArr.length==targetArr.length){ //表单id更改,替换原来的信息
              newcomArr[k] = newObj
              arr = newcomArr
            }else{ //表单新增,数组添加新的信息
              arr = [...newcomArr, newObj]
            }
            arr.reduce((one,two)=>{
              obj[two.aucrId] ? "" : obj[two.aucrId] = true && one.push(two);
              return one;
            },[]).sort((a, b)=> { //去重并按表单指定顺序返回
                if(a.aucrName!='无'&&b.aucrName!='无'){
                  return targetArr.indexOf(a.aucrId+'') - targetArr.indexOf(b.aucrId+'');
                }else{
                  console.log('这里')
                  if(a.aucrName=='无'){
                      arr.splice(a.aucrId,1,a)
                  }else{
                      arr.splice(b.aucrId,1,b)
                  }
                }
            });
         
            this.setState({
              companyArr: arr
            },()=>{
              console.log(this.state.companyArr)
            })
        }
      }
    })
  }

效果图:表单添加 31f0b8d92933381d48aa16b1f9bef45.png 效果图:表单删除 a5acad77350fd8dbe5bc28297a450ba.png 效果图:表单某项修改 2754e566cf13601072e54590c5407ca.png

OK,大概是没啥问题了