Piotr
Piotr

Reputation: 145

Reactjs Dynamic Form Getting Error OnChnage input value?

I am created a dynamic form in react.js but i can not type anything value in input because onchnage function not working i don't know why i tried a lot of times but i am getting failed and adding form and deleting form is working all right only input value not working here is my code and codesandbox link https://codesandbox.io/s/reactdynamicform-02cho .

import React, { Component } from "react";
import "bootstrap/dist/css/bootstrap.css";

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      inputFields: [
        {
          firstName: "",
          lastName: ""
        }
      ]
    };

  }

  handleAddFields = () => {
    const values = this.state.inputFields;
    values.push({ firstName: "", lastName: "" });
    this.setState({
      values
    });
  };

  handleRemoveFields = index => {
    const values = this.state.inputFields;
    values.splice(index, 1);
    this.setState({
      values
    });
  };

  async onChange(e, index) {
    if (
      ["firstName","lastName"].includes(e.target.name)
    ) {
    let cats = [...this.state.inputFields];
    cats[index][e.target.name] = e.target.value;
    await this.setState({
      cats
    });
  }else{
    this.setState({ [e.target.name]: e.target.value.toUpperCase() });
  }
    console.log(this.state.inputFields);
  }

  handleSubmit = e => {
    e.preventDefault();
    console.log("inputFields", this.state.inputFields);
  };

  render() {
    return (
      <>
        <h1>Dynamic Form Fields in React</h1>
        <form onSubmit={this.handleSubmit.bind(this)}>
          <div className="form-row">
            {this.state.inputFields.map((inputField, index) => (
              <div key={`${inputField}~${index}`}>
                <div className="form-group col-sm-6">
                  <label htmlFor="firstName">First Name</label>
                  <input
                    type="text"
                    className="form-control"
                    id="firstName"
                    name="firstName"
                    value={inputField.firstName}
                    onChange={this.onChange.bind(index)}
                  />
                </div>
                <div className="form-group col-sm-4">
                  <label htmlFor="lastName">Last Name</label>
                  <input
                    type="text"
                    className="form-control"
                    id="lastName"
                    name="lastName"
                    value={inputField.lastName}
                    onChange={this.onChange.bind(index)}
                  />
                </div>
                <div className="form-group col-sm-2">
                  <button
                    className="btn btn-link"
                    type="button"
                    onClick={() => this.handleRemoveFields(index)}
                  >
                    -
                  </button>
                  <button
                    className="btn btn-link"
                    type="button"
                    onClick={() => this.handleAddFields()}
                  >
                    +
                  </button>
                </div>
              </div>
            ))}
          </div>
          <div className="submit-button">
            <button
              className="btn btn-primary mr-2"
              type="submit"
              // onSubmit={this.handleSubmit}
            >
              Save
            </button>
          </div>
          <br />
          <pre>{JSON.stringify(this.state.inputFields, null, 2)}</pre>
        </form>
      </>
    );
  }
}

export default App;

Upvotes: 0

Views: 648

Answers (3)

Mathias Bradiceanu
Mathias Bradiceanu

Reputation: 362

1) Since your inputFields state is an array, you can't just call this.state.inputFields.firstName and even less inputField.firstName.

You have to call this.state.inputsFields[0].firstName.

 

2) If you want the index AND the event, you have to pass the onChange event like this :

<input
  type="text"
  className="form-control"
  id="lastName"
  name="lastName"
  onChange={event => this.handleChange(event, index)}
/>
  handleChange = (event, index) => {
    console.log(event.currentTarget.value, index);
  };
// output : {whatever you type} {index of the form}
// exemple : "hello 1"

Upvotes: 0

itamar
itamar

Reputation: 3967

try this onChange={(e)=>{this.onChange(e, index)}}

instead of

onChange={this.onChange.bind(index)}

Upvotes: 1

Zohaib Ijaz
Zohaib Ijaz

Reputation: 22885

You approach is not the correct. Use object to contain form values

state = { 
    inputFields: { firstName: '', lastName: '' }
}


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


// in jsx

<input name="firstName" onChange={this.onChange} />

Upvotes: 1

Related Questions