0

I'm working on a project named "Food Recipes", where a user can create, edit, delete his own recipes.

When creating a new recipe, the user must select the ingrediets. So here is where I need your help:

By an axios call, I'm getting all the ingredients and show them into a table. The table looks like this:

|---------------------|------------------|-----------------|
|      Ingredient     |    Check         |     Amount      |
|---------------------|------------------|-----------------|
|      Tomato         |     true         |      2 kg       |
|---------------------|------------------|-----------------|
|      Potato         |     false        |                 |
|---------------------|------------------|-----------------|
|      Onion          |     true         |      1 kg       |
|---------------------|------------------|-----------------|

After checking some ingredient to TRUE, I want to have onChange function that will create list of IDs, from all ingredients that are CHECKED (in this case, I will have list with two elements: ID from Tomato, and ID from Onion)

To mention, i put ingredient ID as a value inside the <input type="checkbox"/>

Here is my code:

import React, {Component, useEffect, useState} from 'react'
import axios from "../../../axios/axios"

class Ingredient extends Component {
    constructor(props){
        super(props)
        this.state = {
            ingredients: [],
            ingedientsList: [],
            isChecked: false,
        }
    }
    onIngredientChange = (e) => {
          //HERE
    };

    componentDidMount() {
        axios.get("/ingredients").then((data) => {
            const ingredients = Object.keys(data.data).map((ingredient, index) => {
                return (
                    <tr key={index}>
                        <td scope="col">
                            <label>{data.data[index].name}</label>
                        </td>
                        <td scope="col">
                            <input
                                id={data.data[index].id}
                                key={index}
                                type="checkbox"
                                name={"newIngredients"}
                                value={data.data[index].id}
                                onChange={this.onIngredientChange}

                            />
                        </td>
                        <td scope="col">
                            <input
                                id={data.data[index].id + "amount"}
                                key={index}
                                type="number"
                                min="0"
                                max="500"
                                name="amount"
                                placeholder="grams"
                                onChange={this.onIngredientChange}
                            />
                        </td>
                    </tr>
                );
            });
            this.setState({ingredients: ingredients});
        });
    }
    render() {
        return (
            <div className="form-group">
                <table className="table tr-history table-striped small">
                    <thead>
                    <tr>
                        <th scope="col">
                            <h5>Ingredient</h5>
                        </th>
                        <th scope="col">
                            <h5>Check</h5>
                        </th>
                        <th scope="col">
                            <h5>Amount</h5>
                        </th>
                    </tr>
                    </thead>
                    <tbody>
                    {this.state.ingredients}
                    </tbody>
                </table>
            </div>
        )
    }
}
export default Ingredient;
1
  • Is it an option to loop over all the checkboxes, when a checkbox changes? Commented May 12, 2020 at 9:29

3 Answers 3

1

Update

Try the code below.

const data = {
   data:[
     {
       id:1,
       name:"A"
     },
     {
       id:2,
       name:"B"
     },
     {
       id:3,
       name:"C"
     }
   ]
}


class Ingredient extends React.Component {
    constructor(props){
        super(props)
        this.state = {
          ingredients: [],
          ingedientsList: [],
          checkedList:[],
          isChecked: false,
        }
    }
    
        componentDidMount() {
            const ingredients = data.data.map((ingredient, index) => {
                return (
                    <tr key={index}>
                        <td scope="col">
                            <label>{data.data[index].name}</label>
                        </td>
                        <td scope="col">
                           <input
                              id={data.data[index].id}
                              key={index}
                              type="checkbox"
                              name={"newIngredients"}
                              value={data.data[index].id}    
                              onChange={(e)=>this.onIngredientChange(e,data.data[index].id)}
                            />
                        </td>
                        <td scope="col">
                            <input
                                id={data.data[index].id + "amount"}
                                key={index}
                                type="number"
                                min="0"
                                max="500"
                                name="amount"
                                placeholder="grams"
                                onChange={this.onIngredientChange}
                            />
                        </td>
                    </tr>
                );
            });
            this.setState({ingredients: ingredients});
    }
    
     onIngredientChange = (e,id) => {
     let resultArray = []
     if(e.target.checked)      //if checked (true), then add this id into checkedList
     {
          resultArray = this.state.checkedList.filter(CheckedId=>
            CheckedId !== id
          )
          resultArray.push(id) 
     }
     else                    //if not checked (false), then remove this id from checkedList
     {
        resultArray = this.state.checkedList.filter(CheckedId=>
            CheckedId !== id
        )
     }
     console.log(resultArray)

     this.setState({
        checkedList:resultArray
     })
     }
    
    
    
    render() {
        return (
            <div className="form-group">
                <table className="table tr-history table-striped small">
                    <thead>
                    <tr>
                        <th scope="col">
                            <h5>Ingredient</h5>
                        </th>
                        <th scope="col">
                            <h5>Check</h5>
                        </th>
                        <th scope="col">
                            <h5>Amount</h5>
                        </th>
                    </tr>
                    </thead>
                    <tbody>
                    {this.state.ingredients}
                    </tbody>
                </table>
            </div>
        )
    }
}
// Render it
ReactDOM.render(
  <Ingredient />,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="react"></div>

First, have a checked list in state

    this.state = {
        ingredients: [],
        ingedientsList: [],
        checkedList:[]
        isChecked: false,
    }

Then change element a little bit,

   <input
       id={data.data[index].id}
       key={index}
       type="checkbox"
       name={"newIngredients"}
       value={data.data[index].id}    
       onChange={(e)=>this.onIngredientChange(e,data.data[index].id)}
    />

Then change handler,

onIngredientChange = (e,id) => {
     let resultArray = []
     if(e.target.checked)      //if checked (true), then add this id into checkedList
     {
        resultArray = this.state.checkedList.filter(CheckedId=>
            CheckedId !== id      //  filter(checkID=>{CheckedId !== id}) remove {} 
        )
        resultArray.push(id)
     }
     else                    //if not checked (false), then remove this id from checkedList
     {
        resultArray = this.state.checkedList.filter(CheckedId=>
            CheckedId !== id      //  filter(checkID=>{CheckedId !== id}) remove {} 
        )
     }

     this.setState({
        checkedList:resultArray
     })

     console.log(resultArray)   // get all checked ID
};
Sign up to request clarification or add additional context in comments.

1 Comment

Hello. Everytime I check different ingredient, the resultArray starts from being empty. When I check Tomato(which ID is 9) the resultArray is 9. When I click Potato(which ID is 8) the resultArray is 8, instead of being [9,8].
0

Try this. Use a state array instead of simple array.

onIngredientChange = (e, value) => {
         if (array.includes(value) && !e.target.checked) {
           array.splice( array.indexOf(value), 1 );
         } else if (!array.includes(value) && e.target.checked) {
           array.push(value)
         }
    };

<input id={data.data[index].id} key={index}
    type="checkbox" name={"newIngredients"}
     value={data.data[index].id}
     onChange={(e) =>this.onIngredientChange(e, value)} />

Comments

0
...
onIngredientChange = e => {
  const checkedIngrediants = {
    ...this.state.checkedIngrediants
    [e.target.id]: !e.target.value
  };
  this.setState({
    checkedIngredients,
    ingredientsList: Object.keys(checkedIngredients)
      .filter(key => checkedIngredients[key])
  })
}
...
<input
  id={data.data[index].id}
  key={index}
  type="checkbox"
  name={"newIngredients"}
  value={this.state.checkedIngrediants[data.data[index].id]}
  onChange={this.onIngredientChange} />

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.