如何在React.js的Edit阶段管理动态控制的表单?

时间:2019-06-19 12:59:22

标签: javascript reactjs

我创建了一个带有按钮的动态控制表单,用户可以使用该按钮为每次单击按钮添加新字段,如类别和上传选项。目前,我正在研究同一字段的编辑选项。从后端获取数据并在表单组件中设置其值时,我遇到了问题。请给我您的宝贵建议。下面是我的表单的代码段。

class Form extends Component {
  constructor(props) {
    super(props);
    this.state = {
      mask: this.props.currentMask,
      isNew: this.props.isNew,
      inProgress: false,
      existingMaskFiles: [],
      deletedMaskFiles: [],
      isHidden: true,
      maskImages: [
        {
          uid: '1',
          mask_type_id: "",
          image: ""
        }
      ]
    };
    this.handleOnChange = this.handleOnChange.bind(this);
    this.handleSave = this.handleSave.bind(this);
    this.handleChange = this.handleChange.bind(this);
    this.beforeFileUpload = this.beforeFileUpload.bind(this);
    this.handleBannerFileDelete = this.handleBannerFileDelete.bind(this);
    this.deleteMaskImages = this.deleteMaskImages.bind(this);
  }

  componentWillMount() {
    if (!this.props.isNew) {
      const existingMaskFiles = [];
      _.forEach(this.props.currentMask.mask_images, mask => {
        if (mask.image_url !== null) {
          existingMaskFiles.push({
            uid: mask.id,
            id: mask.id,
            mask_type_id: mask.point_id,
            name: mask.image_url.substring(mask.image_url.lastIndexOf('/') + 1) || '',
            image: mask.image_url
          });
        }
      });
      this.setState({existingMaskFiles})

    } else {
      this.setState({mask: Object.assign({}, this.state.mask)});
    }
  }

  handleOnChange = (element, value, index) => {
    if (element === "mask_type_id") {
      let maskImages = [...this.state.maskImages]
      maskImages[index][element] = value
      this.setState({maskImages})
    }
  }

  handleImageChange = (element, filelist, index) => {
    const imageFile = [filelist.file];
    if (element === "image") {
      let maskImages = [...this.state.maskImages]
      maskImages[index][element] = imageFile
      this.setState({maskImages})
    }
  }

  handleBannerFileDelete(id) {
    let maskImages = [...this.state.maskImages]
    maskImages[id].image = "";
    this.setState({maskImages: maskImages})
  }

  deleteMaskImages(id) {
    const key = _.find(this.state.existingMaskFiles, fileObj => id === fileObj.id);
    const result = this.state.existingMaskFiles.splice(key, 1);
    const deletedMaskFiles = this.state.deletedMaskFiles;
    deletedMaskFiles.push(result[0].id);
    this.setState({existingMaskFiles: this.state.existingMaskFiles, deletedMaskFiles})

  }
  addMask = (e) => {
    console.log("Add mask is called");
    this.setState((prevState) => ({
      maskImages: [
        ...prevState.maskImages, {
          uid: '1',
          mask_type_id: "",
          image: ""
        }
      ]
    }));
  }

  handleChange(element, value) {
    this.setState({mask: Object.assign({}, this.state.mask, {[element]: value})})
  }

  handleSave() {
    const existingMaskFiles = this.state.existingMaskFiles
    this.setState({inProgress: true, maskImages: existingMaskFiles});
    let maskObj = this.state.mask;
    let images = [];

    const obj = {
      remove_images: this.state.deletedImgFiles,
      mask_images: this.state.maskImages
    }
    if (images.length > 0) {
      obj.mask_images = images;
    }
    const data = Object.assign({}, maskObj, obj);
    this.setState({mask: data});
    saveMask(this.state.isNew, data).then((result) => {
      if (result.success) {
        this.setState({inProgress: false});
        this.props.onSuccess(I18n.t('masks.saved'));
      } else {
        this.setState({errors: result.errors, inProgress: false});
      }
    });
  }

  beforeFileUpload(file) {
    return false;
  }

  render() {
    const {mask} = this.state;
    const uploadButton = (<Button style={{
        marginTop: '5px'
      }}>
      <Icon type="upload"/>
      Click to Upload
    </Button>)
    const Option = Select.Option;

    return (<div>
      <Row gutter={16}>
        <Col xs={12}>
          <FormItem label="Name">
            <Input value={mask.name} onChange="onChange" {e => this.handleChange('name', 
                              e.target.value)}/>
          </FormItem>
        </Col>
      </Row>
      <Row>
        <Button onClick={this.addMask}>Add More Masks</Button>
        {
          this.state.maskImages.map((val, idx) => {
            let ID = idx;
            return (<div key={idx}>
              <Row gutter={16}>
                <Col xs={10} sm={10}>
                  <FormItem label="Category">
                    <Select style={{
                        width: 120
                      }} value={this.state.maskImages[idx].mask_type_id} onChange="onChange" {e=>this.handleOnChange('mask_type_id', e, ID)}>
                      <Option value="4">4</Option>
                      <Option value="5">5</Option>
                      <Option value="6">6</Option>
                    </Select>
                  </FormItem>
                </Col>
                <Col xs={10} sm={10}>
                  <FormItem label="Upload Image">
                    <Upload key={idx} fileList={[this.state.maskImages[idx]]} onChange="onChange" {e=>this.handleImageChange('image', e, ID)} beforeUpload={this.beforeFileUpload} showUploadList={{
                        showPreviewIcon: false,
                        showRemoveIcon: true
                      }} <Button style={{
                        marginTop: '5px'
                      }}>
                      <Icon type="upload"/>
                      Click to Upload
                    </Button>
                  </Upload>
                  {
                    this.state.existingMaskFiles[idx] && <Row>
                        <Col xs={24}>
                          <List size="small" dataSource={[this.state.existingMaskFiles[idx]]} renderItem="renderItem" { item => 
                                      (<List.Item
                                        className="img-list-item" 
                                        actions={[<Icon type="close" 
                                          className="close-icon" 
                                         onClick={e => 
                                    this.deleteMaskImages(idx)} />]}>
                                      <Icon type="paper-clip" 
                                         className="picture-img" />
                                            {item.name !=null ? 
                                       item.name :''}
                                      </List.Item>)
                                      }/>
                        </Col>
                      </Row>
                  }
                </FormItem>
              </Col>
            </Row>
          </div>
          )
              })
            }
      </Row>
      <Row>
        {FormErrors(this.state.errors)}
      </Row>
      <Row>
        <Col xs={24}>
          {FormButtons(this.state.inProgress, this.handleSave, this.props.onCancel)}
        </Col>
      </Row>
    </div>);
  }
}
export default Form;

1 个答案:

答案 0 :(得分:0)

我找到了问题的解决方案并将其实现。问题是没有处理来自数据库的数据的功能。在componentWillReceiveProps中,我试图将来自DB的props数据分配给一个Array。我试图将该Array映射到render中如果是编辑表单,则在ComponentWillReceiveProps中有数据,以便显示数据;如果是新表单,则无数据;如果他尝试再添加一个formInput,我们将有Other Array处理它。相同形式的编辑功能有点笨拙。希望它对某人有帮助

    <Row>
      <Button onClick={this.addMask}>Add More Masks</Button>
        {
          this.state.maskImages.map((val, idx)=> {
            let ID=idx; 
            return (
              <div key={idx}>
                <Row gutter={16}>
                  <Col xs={10} sm={10}>
                    <FormItem label={I18n.t('masks.mask_type')}>
                      <Select
                        style={{ width: 120 }} 
                        value={val ? val.mask_type_id : ''}
                        onChange={e=>this.handleOnChange('mask_type_id', e, ID)}
                      >
                        {
                          this.state.maskTypes.map((masktype) => {
                            return (
                              <Option key={masktype.id} value={masktype.id}>{masktype.name}</Option>
                            );
                          })
                        }
                      </Select>
                    </FormItem>
                  </Col>
                  <Col xs={10} sm={10}>
                    <FormItem label={I18n.t('masks.mask_image')}>
                      <Upload 
                        key={idx}
                        fileList={val.image !== '' ? [val] : ''}
                        beforeUpload={this.beforeFileUpload}
                        onChange={e=>this.handleImageChange('image', e, ID)}
                        showUploadList={{ showPreviewIcon: false, showRemoveIcon: true }}
                        onRemove={e=>this.deleteNewMaskImages(ID)}
                      >
                        { val.image == '' && uploadButton }
                      </Upload>         
                    </FormItem>
                  </Col>
                </Row> 
              </div>
            )
          })
        }
        {
          this.state.existingMaskFiles.map((val, idx)=> {
            let ID=idx; 
            return (
              <div key={idx}>
                <Row gutter={16}>
                  <Col xs={10} sm={10}>
                    <FormItem label={I18n.t('masks.mask_type')}>
                      <Select
                        style={{ width: 120 }} 
                        value={val ? val.mask_type_id : this.state.editMaskImages.mask_type_id}
                        onChange={e=>this.handleOnEditChange('mask_type_id', e, ID)}
                      >
                        {
                          this.state.maskTypes.map((masktype) => {
                            return (
                              <Option key = {masktype.id} value = {masktype.id}>{masktype.name}</Option>
                            );
                          })
                        }
                      </Select>
                    </FormItem>
                  </Col>
                  <Col xs={10} sm={10}>
                    <FormItem label={I18n.t('masks.mask_image')}>
                      <Upload 
                        key={idx}
                        fileList={val.image !== '' ? [val] : ''}
                        beforeUpload={this.beforeFileUpload}
                        onChange={e=>this.handleOnEditImageChange('image', e, ID)}
                        showUploadList={{ showPreviewIcon: false, showRemoveIcon: true }}
                        onRemove={e=>this.deleteMaskImages(ID)}
                      >
                        { val.image == '' && uploadButton }  
                      </Upload>
                    </FormItem>
                  </Col>
                </Row> 
              </div>
            )
          })
        }
    </Row>