最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Add multiple input field dynamically in react - Stack Overflow

programmeradmin1浏览0评论

I have is a div that contains three input elements and a remove button. what is required is when the user clicks on the add button it will add this div dynamically and when the user clicks on the remove button it will remove this div. I was able to add one input element (without div container) dynamically with the following method.

  • create an array in the state variable.
  • assign a name to the dynamic input field with the help of array indexing like name0, name1

How can I do with these many input fields? The problem grows further when I create this whole div as a separate ponent. I am using a class-based ponent.

handleChange=(event) =>
  {
    this.setState({[event.target.name]:event.target.values});
  }

render()
  {
    return(
      <div className="row">
        <button type="button" onClick={this.addElement}>Add</button>
        <div className="col-md-12 form-group">
          <input type="text" className="form-control" name="name" value={this.state.name} onChange={this.handleChange} />
          <input type="text" className="form-control" name="email" value={this.state.email} onChange={this.handleChange} />
          <input type="text" className="form-control" name="phone" value={this.state.phone} onChange={this.state.phone} />
          <button type="button" onClick={this.removeElement}>Remove</button>
        </div> 
      </div>
    )
  }

I have is a div that contains three input elements and a remove button. what is required is when the user clicks on the add button it will add this div dynamically and when the user clicks on the remove button it will remove this div. I was able to add one input element (without div container) dynamically with the following method.

  • create an array in the state variable.
  • assign a name to the dynamic input field with the help of array indexing like name0, name1

How can I do with these many input fields? The problem grows further when I create this whole div as a separate ponent. I am using a class-based ponent.

handleChange=(event) =>
  {
    this.setState({[event.target.name]:event.target.values});
  }

render()
  {
    return(
      <div className="row">
        <button type="button" onClick={this.addElement}>Add</button>
        <div className="col-md-12 form-group">
          <input type="text" className="form-control" name="name" value={this.state.name} onChange={this.handleChange} />
          <input type="text" className="form-control" name="email" value={this.state.email} onChange={this.handleChange} />
          <input type="text" className="form-control" name="phone" value={this.state.phone} onChange={this.state.phone} />
          <button type="button" onClick={this.removeElement}>Remove</button>
        </div> 
      </div>
    )
  }

Share Improve this question edited Jan 21, 2022 at 0:56 halfer 20.4k19 gold badges109 silver badges202 bronze badges asked Dec 8, 2021 at 7:05 Pranay kumarPranay kumar 2,1974 gold badges31 silver badges59 bronze badges 4
  • Are you trying to add/remove the div, or add/remove inputs? You question jumps between the two scenarios. If it's inputs how do you determine what type of input it is before you add it? – Andy Commented Dec 8, 2021 at 7:11
  • this might be helpful for u:bapunawarsaddam.medium./… – greetal Commented Dec 8, 2021 at 7:12
  • @Andy I am trying to add a div that contains the inputs. type of input is static and does not change. – Pranay kumar Commented Dec 8, 2021 at 7:13
  • @Pranaykumar you could use an array/object and map it to return the required ponent. and use a state to push to array and it will render the ponent for you – Arshal Daison Commented Dec 8, 2021 at 7:41
Add a ment  | 

4 Answers 4

Reset to default 2

I would approach this from a configuration angle as it's a little more scalable. If you want to eventually change across to something like Formik or React Form, it makes the move a little easier.

Have an array of objects that you want to turn into input fields. Your main ponent should maintain state whether the <Form /> ponent is showing, and if it's visible pass in the config and any relevant handlers.

Your form ponent should maintain state for the inputs, and when you submit it, passes up the pleted state to the parent.

const { Component } = React;

class Example extends Component {

  constructor(props) {
    super();

    // The only state in the main ponent
    // is whether the form is visible or not
    this.state = { visible: false };
  }

  addForm = () => {
    this.setState({ visible: true });
  }

  removeForm = () => {
    this.setState({ visible: false });
  }

  handleSubmit = (form) => {
    console.log(form);
  }

  render() {
    
    const { visible } = this.state;
    const { config } = this.props;
    
    return (

      <div>
        <button
          type="button"
          onClick={this.addForm}
        >Add form
        </button>

        {visible && (
          <Form
            config={config}
            handleSubmit={this.handleSubmit}
            handleClose={this.removeForm}
          />
        )}

      </div>
    );
  
  }

};

class Form extends Component {

  constructor(props) {
    super();
    this.state = props.config.reduce((acc, c) => {
      return { ...acc, [c.name]: '' };
    }, {});
  }

  handleChange = (e) => {
    const { name, value } = e.target;
    this.setState({ [name]: value });
  }

  handleSubmit = () => {
    this.props.handleSubmit(this.state);
  }

  render() {

    const { name, email, phone } = this.state;
    const { handleClose, config } = this.props;
        
    return (
      
      <div onChange={this.handleChange}>
        
        {config.map(input => {
          const { id, name, type, required } = input;
          return (
            <div>
              <label>{name}</label>
              <input key={id} name={name} type={type} required={required} />
            </div>
          )
        })}
        
        <button type="button" onClick={this.handleSubmit}>Submit form</button>
        
        <button type="button" onClick={handleClose}>Remove form</button>
      
      </div>
    
    );
  
  }

}

const config = [
  { id: 1, name: 'name', type: 'text', required: true },
  { id: 2, name: 'email', type: 'email', required: true },
  { id: 3, name: 'phone', type: 'phone', required: true }
];


ReactDOM.render(
  <Example config={config} />,
  document.getElementById('react')
);
input { display: block; }
label { text-transform: capitalize; }
<script src="https://cdnjs.cloudflare./ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>

I hope this would be help for your question. I made a child ponent which have three input tags.

// parent ponent
import React, { Component } from "react";
import TextField from "./TextField";

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      users: [
        {
          key: Date.now(),
          name: "",
          email: "",
          phone: ""
        }
      ]
    };
  }

  onChange = (inputUser) => {
    this.setState((prevState) => {
      const newUsers = prevState.users.map((element) => {
        if (element.key === inputUser.key) return inputUser;
        return element;
      });
      return { users: newUsers };
    });
  };

  addElement = () => {
    const { name, email, phone } = this.state;
    this.setState((prevState) => ({
      users: prevState.users.concat({
        key: Date.now(),
        name,
        email,
        phone
      })
    }));
  };

  removeElement = (id) => {
    this.setState((prevState) => ({
      users: prevState.users.filter((user) => user.key !== id)
    }));
  };

  render() {
    const { users } = this.state;
    return (
      <div className="row">
        <button type="button" onClick={this.addElement}>
          Add
        </button>
        <div className="col-md-12 form-group">
          {users.map((user) => (
            <React.Fragment key={user.key}>
              <TextField
                value={user}
                onChange={(inputUser) => this.onChange(inputUser)}
              />
              <button
                type="button"
                onClick={() => this.removeElement(user.key)}
                disabled={users.length <= 1}
              >
                Remove
              </button>
            </React.Fragment>
          ))}
        </div>
      </div>
    );
  }
}

export default App;


// child ponent
import { Component } from "react";

class TextField extends Component {
  handleChange = (ev) => {
    const { name, value } = ev.target;
    this.props.onChange({
      ...this.props.value,
      [name]: value
    });
  };

  render() {
    const { value: user } = this.props;
    return (
      <>
        <input
          className="form-control"
          name="name"
          value={user.name}
          onChange={this.handleChange}
          placeholder="name"
          type="text"
        />
        <input
          className="form-control"
          name="email"
          value={user.email}
          onChange={this.handleChange}
          placeholder="email"
          type="text"
        />
        <input
          className="form-control"
          name="phone"
          value={user.phone}
          onChange={this.handleChange}
          placeholder="phone"
          type="text"
        />
      </>
    );
  }
}

export default TextField;

You can also check the code in codesandbox link below. https://codesandbox.io/s/suspicious-heisenberg-xzchm

It was a little difficult to write down every detail of how to generate what you want. So I find it much easier to ready a stackblitz link for you to see how is it going to do this and the link is ready below:

generating a dynamic div adding and removing by handling inputs state value

const { Component } = React;

class Example extends Component {

  constructor(props) {
    super();

    // The only state in the main ponent
    // is whether the form is visible or not
    this.state = { visible: false };
  }

  addForm = () => {
    this.setState({ visible: true });
  }

  removeForm = () => {
    this.setState({ visible: false });
  }

  handleSubmit = (form) => {
    console.log(form);
  }

  render() {
    
    const { visible } = this.state;
    const { config } = this.props;
    
    return (

      <div>
        <button
          type="button"
          onClick={this.addForm}
        >Add form
        </button>

        {visible && (
          <Form
            config={config}
            handleSubmit={this.handleSubmit}
            handleClose={this.removeForm}
          />
        )}

      </div>
    );
  
  }

};

class Form extends Component {

  constructor(props) {
    super();
    this.state = props.config.reduce((acc, c) => {
      return { ...acc, [c.name]: '' };
    }, {});
  }

  handleChange = (e) => {
    const { name, value } = e.target;
    this.setState({ [name]: value });
  }

  handleSubmit = () => {
    this.props.handleSubmit(this.state);
  }

  render() {

    const { name, email, phone } = this.state;
    const { handleClose, config } = this.props;
        
    return (
      
      <div onChange={this.handleChange}>
        
        {config.map(input => {
          const { id, name, type, required } = input;
          return (
            <div>
              <label>{name}</label>
              <input key={id} name={name} type={type} required={required} />
            </div>
          )
        })}
        
        <button type="button" onClick={this.handleSubmit}>Submit form</button>
        
        <button type="button" onClick={handleClose}>Remove form</button>
      
      </div>
    
    );
  
  }

}

const config = [
  { id: 1, name: 'name', type: 'text', required: true },
  { id: 2, name: 'email', type: 'email', required: true },
  { id: 3, name: 'phone', type: 'phone', required: true }
];


ReactDOM.render(
  <Example config={config} />,
  document.getElementById('react')
);
input { display: block; }
label { text-transform: capitalize; }
<script src="https://cdnjs.cloudflare./ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>

发布评论

评论列表(0)

  1. 暂无评论