Subhojit
Subhojit

Reputation: 1541

multiple textfields onChange function issue

There's a plus button to increase the number of textfields in the page. After increasing the textfields, I want to show all the textfield input value at once under, after clicking on the submit button. But here it's giving a problem on the onChange setState issue. How to handle it ? Any help ?

Here's the => DEMO

class App extends Component {

constructor(props) {
    super(props);
    this.state = { 
      arr: [],
      firstname: '',
      lastname: '',
      setarr: [],
      temp: []
    };
    this.addTextfields = this.addTextfields.bind(this);
    this.changeFirstname = this.changeFirstname.bind(this);
    this.changeLastname = this.changeLastname.bind(this);
  }

  addTextfields(e) {
    let htmlContent = [];
    htmlContent.push(
      <div>
        <input type="text" placeholder="first name" onChange={this.changeFirstname} value={this.state.firstname} /> <br/> <br/>
        <input type="text" placeholder="last name" onChange={this.changeLastname} value={this.state.lastname} /> <br/> <br/>
      </div>
    );
    this.setState({ arr: this.state.arr.concat(htmlContent) });
  }

  changeFirstname(e) {
    this.setState({ firstname: e.target.value });
  }

  changeLastname(e) {
    this.setState({ lastname: e.target.value });
  }

  showTexts() {
    console.log(this.state.firstname, this.state.lastname);
    var add = [this.state.firstname, this.state.lastname];
    this.state.temp = this.state.temp.concat(add);
    this.setState({ setarr: this.state.temp, firstname: '', lastname: '' });
    // localStorage.setItem(this.state.arr, 'names');
  }

  render() {
    return (
      <div>
        <div className="App">
          <input type="text" onChange={this.changeFirstname} placeholder="first name" value={this.state.firstname} /> <br/> <br/>
          <input type="text" onChange={this.changeLastname} placeholder="last name" value={this.state.lastname} /> <br/> <br/>
          <button type="submit" onClick={this.addTextfields}>Plus</button>
          {this.state.arr}
        </div>
        <div className="submit-button">
          <button type="submit" onClick={this.showTexts.bind(this)}>Submit</button>
        </div>
        <div>
          {this.state.setarr}
        </div>
      </div>
    );
  }
}

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

Upvotes: 0

Views: 106

Answers (2)

Amanshu Kataria
Amanshu Kataria

Reputation: 3376

Do it this way.

import React, { Component } from "react";
import { render } from "react-dom";

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      arr: [
        {
          firstname: "",
          lastname: ""
        }
      ],
      displayValues: []
    };
    this.addTextfields = this.addTextfields.bind(this);
    this.changeFirstname = this.changeFirstname.bind(this);
    this.changeLastname = this.changeLastname.bind(this);
  }

  addTextfields(e) {
    let arr = this.state.arr;
    arr.push({
      firstname: "",
      lastname: ""
    });
    this.setState({ arr });
  }

  changeFirstname(e, index) {
    let arr = this.state.arr;
    arr[index].firstname = e.target.value;
    this.setState({ arr });
  }

  changeLastname(e, index) {
    let arr = this.state.arr;
    arr[index].lastname = e.target.value;
    this.setState({ arr });
  }

  showTexts() {
    let displayValues = [];
    this.state.arr.map(element => {
      console.log(element.firstname, element.lastname);
      var add = element.firstname + " " + element.lastname;
      displayValues.push(add);
    });
    this.setState({ displayValues });
  }

  render() {
    return (
      <div>
        <div className="App">
          {this.state.arr.map((element, index) => {
            return (
              <div key={index}>
                <input
                  type="text"
                  onChange={e => this.changeFirstname(e, index)}
                  placeholder="first name"
                  value={this.state.firstname}
                />{" "}
                <br /> <br />
                <input
                  type="text"
                  onChange={e => this.changeLastname(e, index)}
                  placeholder="last name"
                  value={this.state.lastname}
                />{" "}
                <br /> <br />
              </div>
            );
          })}
          <button type="submit" onClick={this.addTextfields}>
            Plus
          </button>
        </div>
        <div className="submit-button">
          <button type="submit" onClick={this.showTexts.bind(this)}>
            Submit
          </button>
        </div>
        <div>
          {this.state.displayValues.map(element => {
            return <p>{element}</p>;
          })}
        </div>
      </div>
    );
  }
}

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

Edit zwln33q3vx

Upvotes: 1

Dev
Dev

Reputation: 3932

I think, you are doing it the wrong way. I have created the below sample for reference. Please have a look.

const Form = (props) => {
  return(
    <div>
        <input type="text" placeholder="first name" onChange={props.changeFirstname} value={props.firstname} /> <br/> <br/>
        <input type="text" placeholder="last name" onChange={props.changeLastname} value={props.lastname} /> <br/> <br/>
    </div>
  )
}

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { 
      arr: [
        {
          firstname: '',
          lastname: '',
          id:1
        }
      ],
      showOutput:false
    };
    this.addTextfields = this.addTextfields.bind(this);
    this.changeFirstName = this.changeFirstName.bind(this);
    this.changeLastName = this.changeLastName.bind(this);
  }

  addTextfields(e) {
    debugger
    let oldArray = this.state.arr;
    this.setState((prevState) => { 
      return {
        arr: oldArray.concat({
          firstname: '',
          lastname: '',
          id: prevState.arr.length + 2
        })
      }
    });
  }

  changeFirstName(e, selectedIndex) {
    let updatedArray =  this.state.arr.map((data) => {
      if(data.id === selectedIndex) {
        return Object.assign({}, data, {
          firstname: e.target.value
        })
      } else {
        return data
      }
    })

    this.setState({ arr: updatedArray });
    
  }

  changeLastName(e, selectedIndex) {
    let updatedArray =  this.state.arr.map((data) => {
      if(data.id === selectedIndex) {
        return Object.assign({}, data, {
          lastname: e.target.value
        })
      } else {
        return data
      }
    })
    this.setState({ arr: updatedArray });
  }

  showTexts() {
    this.setState({
      showOutput: true
    })
  }

  render() {
    return (
      <div>
        <div className="App">
          {
            this.state.arr.map((data, index) => {
              return <Form key={index} data={data} 
                      changeFirstname={(e) => this.changeFirstName(e, data.id)}
                      changeLastname={(e) => this.changeLastName(e, data.id)}
                    />
            })
          }
          <button type="submit" onClick={this.addTextfields}>Plus</button> 
        </div>
        <div className="submit-button">
          <button type="submit" onClick={this.showTexts.bind(this)}>Submit</button>
        </div>
        <div>
          {
            this.state.showOutput && 
            this.state.arr.map((data, index) => {
              return <div>
              {data.firstname}  {data.lastname}
              </div>
            })
          }
        </div>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Hope this helps.

Upvotes: 0

Related Questions