vue 3 radio button revert back if user canceled - javascript

I am having some issues with some radio buttons in vue 3
From the parent component I am passing an object to the child where is the data displayed and where I want to make one version default:
<template>
<table>
...
<tr v-for="(vf, index) in version.files" :key="vf.id">
...
<td>
<input type="radio" name="defaultVersion" v-model="vf.default" :checked="vf.default" #change="onChangeDefault(index)" #click="onClickDefault">
</td>
</tr>
</table>
</template>
props: {
version: Object // the prop object received
},
setup(props) {
const {version} = toRefs(props) // version should be now reactive
// use this variable to know where is the index that contains the default value
let defaultVersionIndex = 0
const onClickDefault = () => {
// check on click what is the current version default and store the index
for(let i = 0; i < version.value.files.length; i++) {
if(version.value.files[i].default) {
defaultVersionIndex = i
}
}
}
const onChangeDefault = (index) => {
let text = "Change default?\nEither OK or Cancel.";
if (confirm(text) == true) {
// user press ok => make API call
} else {
// if the user canceled => set the default radio checked (previously)
version.value.files[index].default = false // change back from what user has selected
version.value.files[defaultVersionIndex].default = true // set back the original radio checked (previously)
}
}
return {
version,
onClickDefault,
onChangeDefault
}
}
When click on a radio (unchecked) it changes visually - but in the version.files no changes ... what I am missing ???
You get the idea .... when the user cancel the action to revert back the radio button. I choose radio because only one can be default.
UPDATE 1
make some changes on input by binding the value (to make sure the value is boolean not on, off)
<input type="radio" :value="vf.default" name="defaultVersion" v-model="vf.default" :checked="vf.default" #change="onChangeDefault(index)" #click="onClickDefault">
and on canceled action :
version.value.files[index].default = !version.value.files[index].default
version.value.files[defaultVersionIndex].default = !version.value.files[defaultVersionIndex].default
the values in the object version.files now changes but visually not working like it should...

Solved.
On input:
<input type="radio" :value="vf.id" name="defaultVersion" v-model="defaultValue" :checked="vf.id === defaultValue" #change="onChangeDefault(vf.id)" #click="onClickDefault">
Created a vmodel that hold the id for the default value
const defaultValue = ref(0)
// store the previous default value (id)
let previousDefault = 0
const onClickDefault = () => {
previousDefault = defaultValue.value // this is the magic :)
}
the when the user canceled:
defaultValue.value = previousDefault

Related

The change event is not working unless I press the enter key

I am currently working on a quantity picker for an eCommerce. The quantity picker consists of:
The minus button
The quantity input field: every time the user clicks on either of the quantity buttons, the value gets updated
The quantity text: this is the quantity enclosed in <span> tags
The plus button
Here is the HTML layout for the quantity picker:
<div class="product-form__input product-form__quantity">
<label class="form__label">
Quantity
</label>
<button class="quantity__button minus no-js-hidden" name="minus" type="button" disabled>
-
</button>
<input class="quantity__input"
type="number"
name="quantity"
id="Quantity-{{ section.id }}"
min="1"
value="1"
form="{{ product_form_id }}"
>
<span class="quantity__text">1</span>
<button class="quantity__button plus" name="plus" type="button">
+
</button>
</div>
The JavaScript is as shown below, where quantityPicker.init() is called which includes:
Updating the value of the quantity input field everytime the user clicks on the plus or minus quantity buttons (call the quantityPicker.onButtonClick() function)
When the value of the quantity input field changes, the quantityPicker.onChange() function must be called.
// Quantity picker
let
quantityFields = document.querySelectorAll(".quantity__input"),
quantityButtons = document.querySelectorAll(".quantity__button"),
quantityPicker = {
onButtonClick: function (event) {
let
button = event.target,
picker = button.closest(".product-form__quantity"),
quantity = picker.querySelector(".quantity__input"),
quantityValue = parseInt(quantity.value),
max = quantity.getAttribute("max") ? parseInt(quantity.getAttribute("max")) : null
if (button.classList.contains("plus") && (max === null || quantityValue + 1 <= null)) {
quantity.value = quantityValue + 1
}
else if (button.classList.contains("minus")) {
quantity.value = quantityValue - 1
}
},
onChange: function (event) {
let
field = event.target,
picker = field.closest(".product-form__quantity"),
quantityText = picker.querySelector(".quantity__text"),
shouldDisableMinus = parseInt(event.target.value) === parseInt(field.getAttribute("min")),
shouldDisablePlus = parseInt(event.target.value) === parseInt(field.getAttribute("max")),
minusButton = picker.querySelector(".quantity__button.minus"),
plusButton = picker.querySelector(".quantity__button.plus")
quantityText.innerText = event.target.value
if (shouldDisableMinus) {
minusButton.setAttribute("disabled", "disabled")
} else if (minusButton.getAttribute("disabled") === true) {
minusButton.removeAttribute("disabled")
}
if (shouldDisablePlus) {
plusButton.setAttribute("disabled", "disabled")
} else if (plusButton.getAttribute("disabled") === true) {
plusButton.removeAttribute("disabled")
}
},
init: function () {
// when a button is clicked
quantityButtons.forEach(quantityButton => {
quantityButton.addEventListener("click", function (event) {
quantityPicker.onButtonClick(event)
})
})
// when a quantity is changed
console.log(quantityFields)
quantityFields.forEach(quantityField => {
console.log(quantityField)
quantityField.addEventListener("change", function (event) {
console.log("Value changed!")
quantityPicker.onChange(event);
})
})
}
}
quantityPicker.init()
However, the issue I am experiencing is that even though the value changes when I click on the plus or minus buttons (as indicated by the change in value on the screen), the change event is not working.
The event only fires if I directly type in a value into the input, and then press the Enter / return key. How can I call the quantityPicker.onChange() function every time the value gets updated, without having to press the return key?
Consider using input event. It fires on every input
I figured out the solution for this question. The change nor the input events will not work if they are changed programmatically. In order to trigger the events, I had to use the dispatchEvent() function to trigger those events programmatically, as shown below:
quantity.dispatchEvent(new Event('input'));

Store values from multiple select in react

I have a variable with the number of select items, this number depends on some API, and I want to store the selection of each question into localstorage so each time the page reloads the selection stays remained, I don't know how to do it.
{ Object.entries(this.state.liste).map( ([ke,values]) => {
let question=ke
return (
<div name = "question" >
<h6 className="left">{ke}</h6>
< select className="right" key={values} name = "answer to each question" onChange={(event) =>
this.handleChangeaa(question,event)} >
<option value={this.state.selected} selected disabled hidden onChange={(value)=>
console.log(value)}> Not answered </option>
{Object.values(values).map(key=>{
return (<option key={key.id} id={key}>{key}</option>) })}
</select>
</div>
) })}
In localStorage, you can only set a value as a string. You simply have to insert in the localStorage some pairs of key/values for each questions that have a selected option. In this case, the key will be the id of your question and the value the value of your selected option.
In your handleChangeaa callBack, you will have something like this :
handleChangeaa(question, event) {
// Check before if the localStorage is available
localStorage.setItem(question.id, event.target.value);
}
Then when your form component will be instantiated, you will simply have to retrieve this information from your localeStorage with the localStorage.getItem function :
componentDidMount() {
// Check if localStorage is available
const stateListCpy = {...this.state.liste}
["question1", "question2"].forEach((questionId) => {
const questionValue = localStorage.getItem(questionId);
if (questionValue) {
const questionIndex = stateListCpy.findIndex((questionBlock) => questionBlock.ke === questionId )
if (questionIndex !== -1) {
stateListCpy[questionIndex].values = questionValue;
}
}
})
this.setState({
liste = stateListCpy;
})
}
And with that you will have your selects initialized with the right values from your localStorage.
Good luck !

clicking through saved checkbox states

The below works to save the states of my checkboxes, then sets the items saved back to checked when called in my load__() function; however I need to instead of just setting to checked, I need to actually have them .click() through in my load__() function as the data is not being served otherwise.
function checkSaver() {
user = JSON.parse(localStorage.getItem(user));
var inputs = document.querySelectorAll('input[type="checkbox"]');
user.userAchkData = [];
inputs.forEach(function(input){
user.userAchkData.push({ id: input.id, checked: input.checked });
});
localStorage.setItem(username, JSON.stringify(user));
console.log(JSON.stringify(user));
}
function load_() {
// get saved latest checkbox states, recheck
user = JSON.parse(localStorage.getItem(user));
var inputs = user.userAchkData;
inputs.forEach(function(input){
if (input.id) {
// I need to click through the found checked here
document.getElementById(input.id).checked = input.checked;
}
});
You can check if they're checked and then programmatically trigger a click:
if (input.id) {
// I need to click through the found checked here
const element = document.getElementById(input.id);
element.checked = input.checked;
if (input.checked) element.click();
}
I fiddled around a bit and got to a simple working example for checking saved checkboxes. Maybe you can adapt this to your needs:
const container = document.getElementById('checkboxes');
const data = JSON.parse(localStorage.getItem('checkboxes')) || new Array(3).fill(false);
window.addEventListener('DOMContentLoaded', () => {
[...container.children].forEach((child, i) => { child.checked = data[i]; });
});
container.onchange = ({ target }) => {
data[target.dataset.id] = target.checked;
localStorage.setItem('checkboxes', JSON.stringify(data));
};
<div id="checkboxes">
<input type="checkbox" data-id="0">
<input type="checkbox" data-id="1">
<input type="checkbox" data-id="2">
</div>

How to use document.getelement by id for arrays which are locted in another array

Sample code.
<script>
var app = (function () {
var config = {
X:345,
Y:543,
Z: [
[1,3],
[2,4],
[3,6]
]
};
}());
</script>
Here I want to pass values into Z dynamically from input field. How can i do it? How to access such kind of an object from html using onclick event.
please provide any fiddle example or sample html and js code if you can. Thanks.
I've created an example where values are added to Z based on what you type in an input field. I hope this answers your question, if anything is unclear just ask.
var app = (function () {
var config = {
X:345,
Y:543,
Z: [
[1,3],
[2,4],
[3,6]
]
};
function onFormSubmitted(event) {
// Prevent the browser from actually submitting the form.
event.preventDefault();
const
input = document.getElementById('input');
// Make sure the input was found and it has a value in it.
if (input === null || input.value === '') {
return;
}
// Push the value in the input into Z.
config.Z.push(input.value);
// Reset the form.
event.target.reset();
}
function logConfig() {
console.log(config);
}
function init() {
const
form = document.getElementById('form');
if (form !== null) {
// Listen for the submit event to add the value in the input to Z.
form.addEventListener('submit', onFormSubmitted);
}
}
init();
// Return the logConfig method so it can be called from outside.
return {
logConfig
}
}());
const
logButton = document.getElementById('log');
// Whenever the log button is clicked, log the current app config.
logButton.addEventListener('click', event => {
app.logConfig();
});
<form id="form">
<input type="number" id="input"/>
<button>Add number</button>
</form>
<button id="log" type="button">log config</button>

How do I compare a value from a form dropdown and assign values to hidden fields in the form based on that selection?

I have a form that I need to populate some hidden fields in the form based upon what a user selects from a dropdown selection in the form. I am trying to use the following if else statement.
formObject = document.forms['events_v150810'];
chooseWebinar = formObject.elements["webinarSelection"];
if ((chooseWebinar.options[chooseWebinar.selectedIndex].value) == "1") {
formObject.elements["hf_EventID"].value = 'First Webinar';
formObject.elements["hf_elqCID"].value = '91';
formObject.elements["hf_elqLPID"].value = '25';
formObject.elements["hf_elqSLID"].value = '161';
}
else if ((chooseWebinar.options[chooseWebinar.selectedIndex].value) == "2") {
formObject.elements["hf_EventID"].value = 'Second Webinar';
formObject.elements["hf_elqCID"].value = '101';
formObject.elements["hf_elqLPID"].value = '35';
formObject.elements["hf_elqSLID"].value = '171';
}
else {
formObject.elements["hf_EventID"].value = 'Third Webinar';
formObject.elements["hf_elqCID"].value = '111';
formObject.elements["hf_elqLPID"].value = '45';
formObject.elements["hf_elqSLID"].value = '181';
}
Even though it is returning the correct value in the console and in the form from the dropdown it always populates the form with the items from the if statement. If I change the dropdown to return a value of "2" I still get the first option. I created a variable and assigned chooseWebinar.options[chooseWebinar.selectedIndex].value to it and recieved a value of 1 even when I had selected an item with a different value. I'm not sure why this would be unless it always assigns the value on the initial page load. Any suggestions would be greatly appreciated.

Categories

Resources