Reputation: 39
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;
Upvotes: 0
Views: 5532
Reputation: 687
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
};
Upvotes: 1
Reputation: 583
...
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} />
Upvotes: 0
Reputation: 1227
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)} />
Upvotes: 0