繁体   English   中英

动态添加表单字段 - ReactJs

[英]Add Form Fields Dynamically — ReactJs

我的要求是动态添加表单字段。 我可以在点击按钮+添加标题时动态添加表单组。

在该表单组中,我有一个按钮+添加内容 ,点击该按钮将新的输入元素添加到该组。

我能够相应地修改JSON并记录相同的状态并更新状态。 但我的观点没有按预期呈现。

任何帮助将受到高度赞赏。

Stackblitz: https ://stackblitz.com/edit/react-utjwsu sombed = 1& file = index.js

/ 代码相同 /

import React, { Component } from 'react';
import { render } from 'react-dom';
import { Form, FormGroup, Label, Progress,Button } from 'reactstrap';
import Hello from './Hello';
import './style.css';


const byPropKey = (propertyName, value) => () => ({
    [propertyName]: value,
  });
class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      name: 'React',
      Information:'',
      ImageUrl:'',
      isUploading: false,
      isUploaded: true,
      showProgress: false,
      progress: 0,
      avatarUrl:'',
      ref:'WhitePapersItems',
      formValid: false,
      content: [{Heading: "", Content: [{value:""}]}]
    };

        this.AddContentBox = this.AddContentBox.bind(this);
        this.handleChange = this.handleChange.bind(this);
        this.AddContentInput = this.AddContentInput.bind(this);
  }

  AddContentBox(){
        return this.state.content.map((element,i)=>(
            <div className="header-content" key={i} >
                <div className="heading-content-wrapper">
                <FormGroup>
                <Label className="set-label-pos upload-img" for="Heading">Heading</Label>
                <input className="form-control" onChange={this.handleChange.bind(this, i)}
                    type="text"/>
                </FormGroup>
                <FormGroup>
                <Label className="set-label-pos upload-img" for="Heading">Content</Label>
                <input className="form-control" onChange={this.handleChange.bind(this, i)}
                    type="text"/>
                </FormGroup>
                {/* {this.AddContentInput} */}
                <FormGroup>
                <Button color="success" onClick={this.AddContentInput.bind(this,i)}>+ Add Content</Button>
                </FormGroup>
            </div>
            </div>
        ))
    }

    handleChange(i, e) {
    const { Heading, value } = e.target;
      let content = [...this.state.content];
      content[i] = {...content[i], [Heading]: value};
      this.setState({ content });
   }

   AddContentInput(index, val){
        console.log('Add ContentInput triggered',val,index);       
        const contents = this.state.content;
        contents[index].Content.push({value:''});
        this.setState({content:contents});
        const item = this.state.content[index].Content;
        console.log('item', item)
        return item.map((element, i)=>(
            <FormGroup>
               <Label className="set-label-pos upload-img" for="Heading">Content</Label>
               <input className="form-control" type="text"/>
           </FormGroup>
       ))

        // console.log(this.state)
        // this.addContentField(index);
    }

     addHeading(event){
        event.preventDefault();
        this.setState(prevState => ({ 
            content: [...prevState.content, { Heading: "", Content: [{value:""}] }]
        }))
        this.AddContentBox();
   }

  render() {
    return (
      <div>


        <Form onSubmit={this.onSubmit}>

                <FormGroup>
                    <Label className="set-label-pos upload-img" for="Information">Information</Label>
                    <textarea className="form-control" rows="10" onChange={event => this.setState(byPropKey('Information', event.target.value))}
                        type="text"/>
                </FormGroup>
                {this.AddContentBox()}
                <div className="add-heading-button">
                    <Button color="primary" onClick={this.addHeading.bind(this)}>+ Add Heading</Button>
                </div>
                <FormGroup>
                <input type="hidden" value={this.state.ImageUrl} onChange={event => this.setState(byPropKey('ImageUrl', event.target.value))}/>
                </FormGroup>

                <Button className="btn btn-danger" size="lg" type="submit">+ Add White Papers Item</Button>
                </Form>

      </div>
    );
  }
}

render(<App />, document.getElementById('root'));

为那些可能遇到过这种情况的人回答我自己的问题。

更新我的stackblitz: https ://stackblitz.com/edit/react-utjwsu sombed = 1& file = index.js

我没有渲染所有内容字段而只是尝试渲染一个。

/ 代码在这里 /

import React, { Component } from 'react';
import { render } from 'react-dom';
import { Form, FormGroup, Label, Progress,Button } from 'reactstrap';
import Hello from './Hello';
import './style.css';


const byPropKey = (propertyName, value) => () => ({
    [propertyName]: value,
  });
class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      name: 'React',
      Information:'',
      ImageUrl:'',
      isUploading: false,
      isUploaded: true,
      showProgress: false,
      progress: 0,
      avatarUrl:'',
      ref:'WhitePapersItems',
      formValid: false,
      content: [{Heading: "", Content: [{value:""}]}]
    };

        this.AddContentBox = this.AddContentBox.bind(this);
        this.AddContentInput = this.AddContentInput.bind(this);
        //this.addContentTextBox = this.addContentTextBox.bind(this);
  }

  AddContentInputFields(element) {
    return element.Content.map(content => {
      return (
        <FormGroup>
          <Label className="set-label-pos upload-img" for="Heading">Content</Label>
          <input className="form-control" type="text"/>
        </FormGroup>
      );
    })
  }

  AddContentBox(){
        return this.state.content.map((element,i)=>(
            <div className="header-content" key={i} >
                <div className="heading-content-wrapper">
                <FormGroup>
                <Label className="set-label-pos upload-img" for="Heading">Heading</Label>
                <input className="form-control" type="text"/>
                </FormGroup>
                { this.AddContentInputFields(element) }
                <FormGroup>
                <Button color="success" onClick={this.AddContentInput.bind(this,i)}>+ Add Content</Button>
                </FormGroup>
            </div>
            </div>
        ))
    }

    handleChange(i, e) {
    const { Heading, value } = e.target;
      let content = [...this.state.content];
      content[i] = {...content[i], [Heading]: value};
      this.setState({ content });
   }

   AddContentInput(index, val){
        console.log('Add ContentInput triggered',val,index);       
        const contents = _.cloneDeep(this.state.content);
        contents[index].Content.push({value:''});

        const item = contents[index].Content;
        console.log('item', item);
        this.setState({content:contents});
        //this.addContentTextBox(item);

    }

    // addContentTextBox(item){
    //   return item.map((element, i)=>(
    //         <FormGroup>
    //            <Label className="set-label-pos upload-img" for="Heading">Content</Label>
    //            <input className="form-control" type="text"/>
    //        </FormGroup>
    //    ));
    // }

     addHeading(event){
        event.preventDefault();
        this.setState(prevState => ({ 
            content: [...prevState.content, { Heading: "", Content: [{value:""}] }]
        }))
        this.AddContentBox();
   }

  render() {
    return (
      <div>


        <Form onSubmit={this.onSubmit}>

                <FormGroup>
                    <Label className="set-label-pos upload-img" for="Information">Information</Label>
                    <textarea className="form-control" rows="10" onChange={event => this.setState(byPropKey('Information', event.target.value))}
                        type="text"/>
                </FormGroup>
                {this.AddContentBox()}
                <div className="add-heading-button">
                    <Button color="primary" onClick={this.addHeading.bind(this)}>+ Add Heading</Button>
                </div>
                <FormGroup>
                <input type="hidden" value={this.state.ImageUrl} onChange={event => this.setState(byPropKey('ImageUrl', event.target.value))}/>
                </FormGroup>

                <Button className="btn btn-danger" size="lg" type="submit">+ Add White Papers Item</Button>
                </Form>

      </div>
    );
  }
}

render(<App />, document.getElementById('root'));

这不能正常工作的原因是因为您直接修改this.state React不会自动重新渲染,因为你没有告诉它状态已经改变了。

您需要调用this.setState()来设置新状态。

如果要添加到对象(例如this.state.content ,则需要确保获取对象的副本(使用类似_.cloneDeep() )以确保不修改现有对象。

希望这足以解释您能够解决您的问题。

更新:您使用以下代码间接修改状态: const contents = this.state.content; contents[index].Content.push({value:''}); const contents = this.state.content; contents[index].Content.push({value:''});

contents是一个变量,它不是this.state.content的副本,它是对它的引用。 因此,将值推入对象实际上是直接修改状态。 我很抱歉没有在原来的答案中说清楚

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM