Add and remove objects from array using checkboxes - javascript

I have implemented check-boxes on a screen in react native and what I am trying to achieve is that upon selection of checkbox it would add that object to an array and upon unchecking it would remove it from the array.
I have tried using filter method as well as loops but it doesn't work the way it is required.
for (let i = 0; i<tmp.length; i++){
console.log("length",tmp.length)
if(tmp.id == item.id){
tmp.splice(tmp.indexOf(item.id),1);
// tmp.pop(item)
console.log("POP")
}
else {
tmp.push(item);
console.log("PUSH")
}
}
My array of objects is as follows:
contacts:[
{name:'a', id:1, plant:3},
{name:'b', id:2, plant:1},
{name:'c', id:3, plant:1}
],
Code for checkboxes:
<CheckBox
checked={this.state.selectedCheckList.includes(item.id)? true:false}
onPress={()=>this.onCheckboxPress(item)} color={"#8BC63E"}
/>
I expect the array that I am creating in tmp to be dynamic, in such a way that it removes and adds whole specific objects from the array.
Before:
tmp:[
{name:'a', id:1, plant:3},
{name:'b', id:2, plant:1},
{name:'c', id:3, plant:1}
],
After:
tmp:[
{name:'a', id:1, plant:3},
{name:'c', id:3, plant:1}
],

Although this question is React Native related, all the answers are HTML+JS.
The solution is to create a new array out of existing one and append it to the state:
onCheckboxPress = (item) => {
const selectedCheckList = contacts.filter((contact) => contact.id !== item.id);
this.setState({ selectedCheckList });
}
And then in the component, you check the state with:
<CheckBox
checked={() => this.isInList(item)}
onPress={()=>this.onCheckboxPress(item)} color={"#8BC63E"}
/>
where the function looks like:
isInList = (item) => {
const { selectedCheckList } = this.state;
return selectedCheckList.some((listItem) => listItem.id === item.id);
}
Hope this helps you on.

Try this::
var arr=[];
function change(checkbox)
{
if(checkbox.checked == true)
{
arr.push(checkbox.value);
}
else
{
var j = arr.indexOf(checkbox.value);
arr.splice(j, 1);
}
var stringArr=arr.join(',');
document.getElementById('display').innerHTML=stringArr;
}
<div>
<label>
<input type="checkbox" name="check" value="Check 1" onchange="change(this)">A</label>
<label>
<input type="checkbox" name="check" value="Check 2" onchange="change(this)">B</label>
<label>
<input type="checkbox" name="check" value="Check 3" onchange="change(this)">C</label>
<label>
<input type="checkbox" name="check" value="Check 4" onchange="change(this)">D</label>
</div>
<div id="display">
</div>

Related

How to push checkbox checked values to js object using jquery each function?

I want the checked checkbox values to store in food javascript object like below:
food: {
{id: 1, name: egg }
{id: 2, name: meat}
}
Here's my code:
var exclude_foods = {};
jQuery('input[name=exclude_food]:checked').each(function(){
exclude_foods = Object.assign(exclude_foods, {
id: 1,
name: jQuery(this).val(),
});
});
Any suggestion or help?
You can use jQuery's map() method to do what you require.
Note that it's not clear where the id value is intended to come from, so I set it to the index of the checkbox for this example. This can easily be amended to suit your use case.
$('button').on('click', e => {
var exclude_foods = {
foods: $('input[name="exclude_food"]:checked').map((i, el) => ({
id: i,
name: el.value
})).get()
};
console.log(exclude_foods);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<label>
<input type="checkbox" name="exclude_food" value="egg" />
Egg
</label>
<label>
<input type="checkbox" name="exclude_food" value="meat" />
Meat
</label>
<label>
<input type="checkbox" name="exclude_food" value="nuts" />
Nuts
</label>
<button>Get values</button>

How can I get selected data list and structure the data list

I am trying to structure my input data but I am not getting what I want. The input data is dynamic which will come from the database.
Suppose I have this below JSX. I want to get the value from the user that he selected and also the product title which is exist on the products. Note that list data is dynamic I have hardcoded the values.
{products.map((product, i) => {
return (
<li onChange={(e) => getItemValues(e.target, product)}>
<label className="container_radio">
Medium size
<span>+ $5.00</span>
<input
type="radio"
value={5.00}
name={'Medium size'}
/>
<span className="checkmark"></span>
</label>
</li>
<li onChange={(e) => getItemValues(e.target, product)}>
<label className="container_radio">
Extra Largse size
<span>+ $8.00</span>
<input
type="radio"
value={8.00}
name={'Extra Largse size'}
/>
<span className="checkmark"></span>
</label>
</li>
);
})}
Here is the function to get the data and save it in a state
const getItemValues = (e, product) => {
setItemDetail((prevValue) => [
...prevValue,
{ [e.name]: e.value },
{ title: product.title },
]);
};
The above code output is:
[0: {Extra Largse size: '8.0'}
1: {Medium size: '5.00'}
2: {title: 'Barnes Chapman'}]
I want something like this
[{title: 'Barnes Chapman', options:{extra large size: '8.0',Medium size: '5.00' } }]
To do this you need to find the product details from the ItemDetail array. Try something like below.
const getItemValues = (e, product) => {
setItemDetail((prevValue) => {
const existingProduct = prevValue.find(item => item.title === product.title);
if(existingProduct) {
existingProduct.options = {...existingProduct.options, [e.name]: e.value}
return [...prevValue];
} else { /* new entry */
return [...prevValue, {title: product.title, options:{[e.name]: e.value}}]
}
});
};

How would I sort a prop of an array of objects nondestructively Reactjs?

So I am trying to sort alphabetically an array of objects nondestructively by using state, so I can also return the array back to its original arrangement. I've tried quite a few ways of copying the original array into a new array to sort: JSON methods to carry a deep copy of this.props.getDaycare.toddlers:
constructor(){
super()
this.state = {
newArray: []
}
}
sort = () => {
let initialArray = this.props.getDaycare.toddlers
let copiedInitialArray = JSON.parse(JSON.stringify(initialArray));
console.log(copiedInitialArray)
this.setState({
newArray: copiedInitialArray.sort((t,u) =>{
if (t.name < u.name) {return -1;}
if (t.name > u.name) {return 1;}
return 0;
})
})
}
That didn't seem to work. It did not update the DOM at all, but it did in the console (alphabetically) when I clicked the sort button
0: {id: 84, name: 'Jared Leno', birthday: '2019-09-02', contact: 'Poppy Roberts', phone: 7605551919, …}
1: {id: 88, name: 'Massimo Gandolfini', birthday: '2019-01-06', contact: 'Poppy Roberts', phone: 7605551919, …}
2: {id: 87, name: 'Rosie Perez', birthday: '2018-12-22', contact: 'Poppy Roberts', phone: 7605559091, …}
3: {id: 80, name: 'Samantha Madison', birthday: '2019-01-06', contact: 'Olusoji Akinremi', phone: 7605551919, …}
4: {id: 90, name: 'Sara Waters', birthday: '2018-12-22', contact: 'Jessica Smith', phone: 7605559091, …}
5: {id: 83, name: 'Serena Williams', birthday: '2019-01-06', contact: 'Sara Reynolds', phone: 7605551919, …}
length: 6
[[Prototype]]: Array(0)
I've tried the shallow copying methods as well such as spread, slice, from. Noting but the same result of not updating the DOM but outputting in the console. I've looked everywhere online for this specific issue and I haven't seen any example showing how to effectively deep copy an array of objects for sorting. All the examples were destructive to the original array.
I'm wondering is there any way at all? please help.
To copy a JS Array, you can use Array#slice method. You don't need a deep copy since the values in React are supposed to be immutable.
I believe your problem is elsewhere. My guess is that you're mixing up props and state, which causes to not update DOM as you'd like it to. To know for sure, you'd have to provide the render method.
The recommended way in this case would be to not modify the state when you want to sort, but to sort elements during the render phase/function.
Like this:
const cmp = (a, b) => (a > b) - (a < b);
class SortedList extends React.Component {
constructor(props) {
super(props)
this.state = {
sort: { field: 'name', descending: false },
};
}
render() {
const { field, descending } = this.state.sort;
const mul = descending ? -1 : 1;
const items = this.props.items.slice();
items.sort((a, b) => mul * cmp(a[field], b[field]));
return (
<ul>
{items.map(({id, name}) => <li key={id}>{name}</li>)}
</ul>
);
}
}
In react, you should think of what renders as a function of props and state.
So there is no need to set the sorted array to state, only the sortType, sortDirection, and other factors that might play a part in how the list is sorted.
const List = ({ data }) => {
const [sortType, setSortType] = useState("name"); //name | birthday | contact
const [sortDirection, setSortDirection] = useState("ASC"); //ASC | DESC
const sortBy = (a, b) => {
if (sortDirection === "ASC") {
return (a[sortType] > b[sortType]) - (a[sortType] < b[sortType]);
}
return (b[sortType] > a[sortType]) - (b[sortType] < a[sortType]);
};
const handleChange = (e) => {
const { value, name } = e.target;
if (name === "sortType") {
setSortType(value);
}
if (name === "sortDirection") {
setSortDirection(value);
}
};
return (
<div>
<h2>List</h2>
<form onChange={handleChange}>
<fieldset>
<legend>Sort by</legend>
<label>
Name
<input
type="radio"
name="sortType"
value="name"
defaultChecked={true}
/>
</label>
<label>
Birthday
<input type="radio" name="sortType" value="birthday" />
</label>
<label>
Contact
<input type="radio" name="sortType" value="contact" />
</label>
</fieldset>
<fieldset>
<legend>Direction</legend>
<label>
Ascending
<input
type="radio"
name="sortDirection"
value="ASC"
defaultChecked={true}
/>
</label>
<label>
Descending
<input type="radio" name="sortDirection" value="DESC" />
</label>
</fieldset>
</form>
<ul>
{data.sort(sortBy).map((d, i) => (
<ListItem data={d} key={i} />
))}
</ul>
</div>
);
};

Vue js putting id to v-model

I'm trying to create a question adder for my quiz. Each question has answers, containing IDs:
var questions = [
{
question: "1+1 is",
answers: [
{ id: 0, answer: "1", correct: false },
{ id: 1, answer: "0", correct: false },
{ id: 2, answer: "2", correct: false }
],
correct: [2],
selected: [],
false: [0, 1]
}]
but I don't know how to create an array of objects with IDs. I know that answercorrect, answerfalse1/2 are wrong, but what do I do instead?
Some HTML:
<label>Otázka: <input v-model="question" type="text"></label><br><br>
<label>Správná odpověď: <input v-model="answercorrect" type="text"></label><br><br>
<label>Odpověď: <input v-model="answerfalse" type="text"></label><br><br>
<label>Odpověď: <input v-model="answerfalse2" type="text"></label>
JS:
addQuestion()
{
if (this.question != "")
{
this.questions.push(this.question);
this.question = "";
this.questions.push(this.answers[this.answercorrect, this.answerfalse, this.answerfalse2]);
this.answercorrect = "";
this.answerfalse = "";
this.answerfalse2 = "";
}
}
I would create a function that generates a blank question object, containing an array of generated answer objects.
let answerId = 0;
let questionId = 0;
const createAnswer = () => ({ id: answerId++, answer: '', correct: false })
const createQuestion = () => ({
id: questionId++,
question: '',
answers: [createAnswer()],
})
A component would use those functions to add new questions and answers:
export default {
data() {
return {
questions: [createQuestion()],
};
},
methods: {
addQuestion() {
this.questions.push(createQuestion())
},
addAnswer(q) {
/**
* Since the `answers` object is part of the `questions` object,
* this takes a question as an argument, and adds a new `answer`
* object to its `answers` array.
*/
q.answers.push(createAnswer())
},
},
}
In the template, use v-for to render the questions, and use v-on button-click handlers that bind to the component's addQuestion() and addAnswer():
<template>
<div>
<button #click="addQuestion">Add question</button>
<fieldset class="question" v-for="q in questions" :key="q.id">
<legend>Question: <input v-model="q.question" type="text" /></legend>
<button #click="addAnswer(q)">Add answer</button>
<label class="answer" v-for="answer in q.answers" :key="answer.id">
Answer: <input type="text" v-model="answer.answer" />
Correct: <input type="checkbox" v-model="answer.correct" />
</label>
</fieldset>
</div>
</template>
demo

ReactJs: How can I show the correct questionnaire answer and the total score?

I am new to react and I want to arrange the correct option of each question on the same page. Also, when the question is solved it should show whether it is correct or not. In the end, I need the total score. How can I accomplish that? Thank you for the help in advance.
This what I have done so far..( Normally there are more questions but I had to delete them to post)
const questionsArray = [
{
question: 'When the C programming language has first appeared?',
option1: '1970',
option2: '1971',
option3: '1972'
},
{
question: 'When the Java programming language has first appeared?',
option1: '1994',
option2: '1995',
option3: '1996'
},
];
class QuizAppQuestion extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
currentQuestionIndex: 0,
questions: [],
answers: []
};
}
componentDidMount() {
this.setState({questions: questionsArray})
}
onChangeOption(value) {
const {currentQuestionIndex} = this.state;
let answers = {...this.state.answers};
answers[currentQuestionIndex] = value;
this.setState({answers});
}
handleNext() {
let incrementCurrentQuestionIndex = this.state.currentQuestionIndex + 1;
this.setState({currentQuestionIndex: incrementCurrentQuestionIndex});
}
render() {
const {questions, currentQuestionIndex, answers} = this.state;
if (!questions.length) {
return <div>Loading questions...</div>
}
if (currentQuestionIndex >= questions.length) {
return (<div><h3>End of the quiz</h3></div>)
}
const {question, option1, option2, option3} = questions[currentQuestionIndex];
return (<div>
<h1>Question {currentQuestionIndex + 1}</h1>
<h4>{question}</h4>
<label>
<input type='radio' checked={answers[currentQuestionIndex] === option1} value={option1} onChange={(evt) => this.onChangeOption(evt.target.value)}/>
{option1}
</label>
<br/>
<label>
<input type='radio' checked={answers[currentQuestionIndex] === option2} value={option2} onChange={(evt) => this.onChangeOption(evt.target.value)}/>
{option2}
</label>
<br/>
<label>
<input type='radio' checked={answers[currentQuestionIndex] === option3} value={option3} onChange={(evt) => this.onChangeOption(evt.target.value)}/>
{option3}
</label>
<hr/>
<button onClick={() => this.handleNext()}>Next</button>
</div>);
}
}
You would want to make a separate array that holds the answers, and test the selected answer against the appropriate question/answer in your answers array. So in your case something like:
const answerArray = [
{
question: "When the C programming language has first appeared?",
answer: "option1"
}
]
onSubmit = (selectedAnswer) => { // Selected answer is the option picked from your select menu
if(selectedAnswer === answerArray[currentQuestionIndex].answer) {
// Logic for correct answer
} else {
// Logic for incorrect answer
}
}

Categories

Resources