Farrukh Ayaz
Farrukh Ayaz

Reputation: 340

how to insert data as an array of objects in React JS

my question is a little complicated, I am building a trip-related web application where users can book trips. So I have made a function that increases the number of travelers as the user clicks the + sign. when this function is called it changes the state and another function gets triggered that displays the form to fill in the traveler details. Now this form is rendered according to the number of travelers traveling. how can I set that data in an array of objects?

here's a screenshot guide:

enter image description here

I want the data to be in the state like this:

travelersDetail: [{firstName: 'Farrukh', lastName:'Ayaz', address:'...', city:'Lahore'},
                  {firstName: 'Dwight', lastName:'Schrute', address:'...', city:'Scranton'},
                  {firstName: 'Micheal', lastName:'Scott', address:'...', city:'Scranton'},]

My code:

    // state

        state = {
            NumOfTravellers : 1,
            travelersDetail: [],        
            trip: null,
        }

    // the functions that increases the number of travelers

        handleClick = (e) =>{
            e.preventDefault();
            if(e.target.id == 'plus'){
            this.setState({NumOfTravellers: this.state.NumOfTravellers + 1 })
            
            }
            else if(e.target.id == 'minus'){
               this.state.NumOfTravellers > 1 ? this.setState({NumOfTravellers: 
               this.state.NumOfTravellers - 1 }) : alert("can't be less than that :)")
            }
        }

// the function that returns the traveler details form, according to the number of travelers traveling.

 const numberOfTravelers = () =>{
        var travellers = [];
        
        
        for(let t = 0; t < this.state.NumOfTravellers; t++){
          travellers.push(
            <div >
            <h4> Traveller # {t+1} Details</h4><br/>
            
            <div className="form-row">
            <div className="form-group col-md-6">
              <label htmlFor="firstName">First Name</label>
              <input type="firstName" className="form-control" onChange={this.handleTDChange} id="firstName" placeholder="FirstName" />
            </div>
            <div className="form-group col-md-6">
              <label htmlFor="lastName">Last Name</label>
              <input type="lastName" className="form-control" onChange={this.handleTDChange} id="lastName" placeholder="LastName" />
            </div>
          </div>
          <div className="form-group">
            <label htmlFor="address">Address</label>
            <input type="text" className="form-control" onChange={this.handleTDChange} id="address" placeholder="1234 Main St" />
          </div>
          <div className="form-group">
            <label htmlFor="phoneNumber">Phone Number</label>
            <input type="tel" className="form-control" onChange={this.handleTDChange} id="phoneNumber" placeholder="+92..." />
          </div>
          <div className="form-row">
            <div className="form-group col-md-6">
              <label htmlFor="city">City</label>
              <select onChange={this.handleTDChange} id="city" className="form-control">
              <option selected>Choose...</option>
              <option>Lahore</option>
              <option>Islamabad</option>
              <option>Karachi</option>
              <option>Rawalpindi</option>
              <option>Quetta</option>
              <option>Multan</option>
            </select>
            </div>
            <div className="form-group col-md-4">
              <label htmlFor="state">State</label>
              <select onChange={this.handleTDChange} id="state" className="form-control">
                <option selected>Choose...</option>
                <option>Pakistan</option>
              </select>
            </div>
            <div className="form-group col-md-2">
              <label htmlFor="zip">Zip</label>
              <input type="text" className="form-control" onChange={this.handleTDChange} id="zip" />
            </div>
          </div>    
            </div>);
          
        }
      return travellers
        
      }

Upvotes: 1

Views: 2915

Answers (2)

AbhishekGowda28
AbhishekGowda28

Reputation: 1054

I don't completely understand you problem, what I understand is.

There is a controller, Plus and Minus. On click of Plus a new Traveler form has to be added and on click of minus the last Travelers form will be removed. And also the traveler counter is incremented or decremented based on the button click

You would not want 2 variables, 1 to keep track of the number of travelers and other to store the traveler details, you can maintain only 1 variable. Just have traverlerDetails, we can get the number of travelers form the size of the traverlerDeterails array.

// state values
this.state = {
    travelersDetail: [],
    trip: null,
};


handleClick = (clickEvent) => {
    clickEvent.preventDefault();
    const travelersDetailCopy = [...this.state.travelersDetail];
    if (e.target.id == 'plus') {
        travelersDetailCopy.push({
            firstName: '', lastName: '', address: '', city: '' // Add empty data
        });
    } else if (e.target.id == 'minus') {
        if (this.state.travelersDetail.length === 1) {
            alert("Can't be less than 1");
        } else {
            travelersDetailCopy.pop();
        }
    }
    this.setState({
        travelersDetail: travelersDetailCopy
    });
}

const numberOfTraverlers = () => {
    return this.state.travelersDetail.map((travelerDetails, index) => {
        return (
            <div key={index}>
                <h4> Traveller # {index + 1} Details</h4><br />

                <div className="form-row">
                    <div className="form-group col-md-6">
                        <label htmlFor="firstName">First Name</label>
                        <input type="firstName" className="form-control" onChange={(event) => {this.handleTDChange(event, index, "firstName")}} id="firstName" placeholder="FirstName" />
                    </div>
                    <div className="form-group col-md-6">
                        <label htmlFor="lastName">Last Name</label>
                        <input type="lastName" className="form-control" onChange={(event) => {this.handleTDChange(event, index, "lastName")}} id="lastName" placeholder="LastName" />
                    </div>
                </div>
                <div className="form-group">
                    <label htmlFor="address">Address</label>
                    <input type="text" className="form-control" onChange={(event) => {this.handleTDChange(event, index, "address")}} id="address" placeholder="1234 Main St" />
                </div>
                <div className="form-group">
                    <label htmlFor="phoneNumber">Phone Number</label>
                    <input type="tel" className="form-control" onChange={(event) => {this.handleTDChange(event, index, "phoneNumber")}} id="phoneNumber" placeholder="+92..." />
                </div>
                <div className="form-row">
                    <div className="form-group col-md-6">
                        <label htmlFor="city">City</label>
                        <select onChange={(event) => {this.handleTDChange(event, index, "city")}} id="city" className="form-control">
                            <option selected>Choose...</option>
                            <option>Lahore</option>
                            <option>Islamabad</option>
                            <option>Karachi</option>
                            <option>Rawalpindi</option>
                            <option>Quetta</option>
                            <option>Multan</option>
                        </select>
                    </div>
                    <div className="form-group col-md-4">
                        <label htmlFor="state">State</label>
                        <select onChange={(event) => {this.handleTDChange(event, index, "state")}} id="state" className="form-control">
                            <option selected>Choose...</option>
                            <option>Pakistan</option>
                        </select>
                    </div>
                    <div className="form-group col-md-2">
                        <label htmlFor="zip">Zip</label>
                        <input type="text" className="form-control" onChange={(event) => {this.handleTDChange(event, index, "zip")}} id="zip" />
                    </div>
                </div>
            </div>
        )
    })
}


handleTDChange(event, index, updateField) {
    const arrayCopy = [...this.state.travelersDetail];
    arrayCopy[index][updateField] = event.target.value;
    this.setState({travelersDetail: arrayCopy});
}

Use this.state.travelersDetail.length to display the number of travelers.

Don't use for-loop, make use of built in functions like forEach, map, filter and other methods.

Update : To handle onChange events, you can have multiple handleChange event handler.

But if you want to do it in a single, you can pass few additional argument. First being the actual event, second the index of the travelerDetails object, third being the property that needs to be updated.

There is a much better way of doing this, extract the content in side the map and create a separate component. Which would contain the logic related to the component. With this updation and also maintenance of the code is much easier

Upvotes: 2

Vuk
Vuk

Reputation: 873

You should be using the array.push() method detailed in javascript to add an element to an existing array.

Example

const array = [];
array.push({ id: 'someId', name: 'someName' });

See documentation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push

Upvotes: 0

Related Questions