Vue JS v-model data doesn't update when used with watch - javascript

Here is my code
data() {
return {
crop_mode: 'portrait',
widget_data:''
}
},
watch: {
widget_data: function (val) {
this.crop_mode = val.crop_mode
},
},
This code is inside a modal component. So whenever a modal is opened, "widget_data" changes. And this widget_data has a "crop_mode" which needs to assigned to the data variable "crop_mode"
This works fine if I console.log the val.crop_mode but when I do v-model on crop_mode like below, it doesn't update the checked radio button.
<label class="custom-radio block">
<input
type="radio"
value="portrait"
name="crop_mode"
v-model="crop_mode"
/>
<span>Portrait</span>
</label>
<label class="custom-radio block">
<input
type="radio"
value="landscape"
name="crop_mode"
v-model="crop_mode"
/>
<span>Landscape</span>
</label>
<label class="custom-radio block">
<input
type="radio"
value="square"
name="crop_mode"
v-model="crop_mode"
/>
<span>Square</span>
</label>

You should add deep:true option because It looks like widget_data is an object with nested values:
watch: {
widget_data:{
handler(val) {
this.crop_mode = val.crop_mode
},
deep:true
}
},

Related

Vue: How to display different images based on RadioButton choice

I am facing a problem where I want to display a different image if a radiobutton is selected with Vuejs. It currently only shows the image for the false state since I do not seem to be able to retrieve the state of the button in the way I tried. Here is an example with two buttons:
<template>
<div id="choose-route">
<label>
<input type="radio" name="Radio" id="choice1"
v-on:change="someMethodOne"
/>
<img
:src="checked ? 'icon_checked.png' : 'icon.png'"
/>
</label>
<label>
<input type="radio" name="Radio" id="choice2"
v-on:change="someMethodTwo"
/>
<img
:src="checked ? 'different_icon_checked.png' : 'different_icon.png'"
/>
</label>
</div>
</template>
<script>
export default {
methods: {
someMethodOne () {
// does something
},
someMethodTwo () {
// does another thing
}
}
}
</script>
<style>
</style>
How do I go about changing the image based on the checked state of the radiobutton? I already did it using CSS, but that lead to another problem due to the fact that I use recursive components which is why I am here now.
Use v-model. You can also use watch to do something when checked value change.
There is this exact example on Vue.js' website.
https://v2.vuejs.org/v2/guide/forms.html#Radio
new Vue({
el: "#app",
data: {
checked: null
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input type="radio" id="one" value='One' v-model="checked">
<label for="one">Option one</label>
<br>
<input type="radio" id="two" value="Two" v-model="checked">
<label for="two">Option two</label>
<br>
<span>Checked: {{ checked }}</span>
<br>
<span v-if="checked === 'One'">One is checked!</span>
<span v-else-if="checked === 'Two'">Two is checked!</span>
</div>

Vue -Store Comma Separated Dynamic Checkbox ids in String

I am having a custom checkbox in vue which dynamically gets generated using a v-for loop.I need to get the ids of every checked checkbox and store it in the form of string with comma separated.
For EG: "Male , Female, Other" - these are the checked values.
But as i am generating checkboxes using a v-for the checked values are getting overridden.
Below is the fucntion that gets called on checkbox click.
updateCheckAll(e) {
let checkboxes = [];
if(e.target.checked) {
checkboxes.push(e.target.id);
}
checkboxes.join(',');
}
HTML - These are custom checkboxes.
<formfield v-for="(option,index) in getCheckBoxData" :key="index" :label="option.value">
<checkbox :id="option.key" :value="option.value" #change="updateCheckAll($event)"></checkbox>
</formfield>
You need to keep state of checked checkboxes:
data() {
return {
checked: [],
}
},
//template
<checkbox :id="option.key" :value="option.value" v-model="checked">
That is all you need to do 😉
You can check the vue documentation for more details
https://v2.vuejs.org/v2/guide/forms.html
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
<br>
<span>Checked names: {{ checkedNames }}</span>
new Vue({
el: '...',
data: {
checkedNames: []
}
})
Code pen
https://codepen.io/tonytomk/pen/NWxbeOB

Vue JS Radio button toggle all scenario

So I know how I can toggle all radio buttons in a group but I have a slightly niche case here. I'll try and explain as best I can here with code and comments.
SomeComponent.vue
<template>
<div>
<!-- This checkbox will toggle the selected stated of all radios -->
<input class="toggleAll" type="checkbox" :checked="checked" #change="toggleAll">
<!-- These will either toggle their own checked state or
IF the above checkbox has been checked and all checkbox are selected, it would remove the
checked state from that one
as not all the radios ARE selected anymore -->
<input :checked="checked" class="radio" type="checkbox">
<input :checked="checked" class="radio" type="checkbox">
<input :checked="checked" class="radio" type="checkbox">
<input :checked="checked" class="radio" type="checkbox">
</div>
</template>
<script>
export default {
name: 'SomeComponent',
data() {
return {
checked: false,
}
},
methods: {
toggleAll() {
this.checked = !this.checked;
}
}
}
</script>
So basically, the input with the class of toggleAll will check/uncheck all checkboxes. However, checking any of the others should uncheck the one you clicked plus the toggleAll checkbox, as not all are checked anymore.
I can't seem to get this to work! I basically need to say look for the input with the class of toggleAll and change the data "checked" to false but I don't know how to do it.
TIA
If you don't have any specific preference for the checked states, I would recommend using a list of boolean and toggle their respective states (with Vue.set to overcome the array change detection caveat).
The example below uses a computed setter/getter to reactively tell if all checkboxes are checked, and toggle them at once when the setter gets called.
By the way, I added an extra attribute (indeterminate) that you might find useful.
I'm using the .prop modifier on the "allChecked" checkbox to tell Vue that we want to bind this indeterminate as a DOM property instead of component attribute.
new Vue({
el: '#app',
data() {
return {
checkList: [false, false, false, false]
}
},
computed: {
allChecked: {
get() {
return this.checkList.every(Boolean);
},
set(isChecked) {
for (let index = 0; index < this.checkList.length; index++) {
this.$set(this.checkList, index, isChecked);
}
}
},
indeterminate() {
return !this.allChecked && this.checkList.some(Boolean);
}
}
})
#app > input[type="checkbox"] {
display: block;
}
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.11"></script>
<div id="app">
<label>
<input
v-model="allChecked"
:indeterminate.prop="indeterminate"
class="toggleAll"
type="checkbox" />
Check all
</label>
<input
v-model="checkList[index]"
v-for="(checked, index) of checkList" :key="index"
class="radio"
type="checkbox" />
</div>
It could be that your problem comes from the fact that the #change event only fires when a user interacts with the radio and changes. On the other hand, looking at your code, are you trying to change the main button's status using the checkAll method? In that case, what's the toggleAll referencing in #change="toggleAll"?
In any case, this should do it:
<template>
<div>
<input class="toggleAll" type="checkbox" :checked="checked2" #change="toggleAll">
<input :checked="checked" #change="toggleMain" class="radio" type="checkbox">
<input :checked="checked" #change="toggleMain" class="radio" type="checkbox">
<input :checked="checked" #change="toggleMain" class="radio" type="checkbox">
<input :checked="checked" #change="toggleMain" class="radio" type="checkbox">
</div>
</template>
<script>
export default {
name: 'SomeComponent',
data() {
return {
checked: false,
checked2: false
{
},
methods: {
toggleMain() {
this.checked2 = false;
}
...
}
}
</script>

Vuejs radio button binding input

I am creating edit form page and i run this before the page loaded
beforeMount(){
if(this.$route.meta.mode === 'edit'){
this.initialize = '/api/artikel/edit/' + this.$route.params.id;
this.store = '/api/artikel/update/' + this.$route.params.id;
this.method = 'put';
}
this.fetchData();
},
and in my fetchData() method i just go to server and retrieve corresponding data to my article id.
fetchData(){
var vm = this
axios.get(this.initialize)
.then(function(response){
Vue.set(vm.$data, 'form', response.data.form);
Vue.set(vm.$data, 'rules', response.data.rules);
Vue.set(vm.$data, 'option', response.data.option);
})
.catch(function(error){
})
},
and then in my form i just bind my form data to my input and it works great in input text but not in other like in this question is input radio button
<div class="form-group">
<h5>Publish:</h5>
<label class="radio-inline">
<input type="radio" name="publish" class="styled" value="1" v-model="form.publish">
Yes
</label>
<label class="radio-inline">
<input type="radio" name="publish" class="styled" value="0" v-model="form.publish">
No
</label>
</div>
it supposed to be auto check into radio button according to the value from database... but in my case none of them checked.. but when i check manualy by clicking it... i see using the form.publish value is changed according to which radio button i check using vuejs inspector in chrome
so where do i get it wrong?
Might be a matter of how the value is coming in. Because you set values to 0/1 the radio button model needs a 0 or 1 value, and not a true/false, can you check that that's the case?
look at snipped below, see what changing to true does
new Vue({
el: '#app',
data: {
form: {}
},
methods: {
update () {
// does not work
//var form = { publish: true }
// works
var form = { publish: 1 } // <---- are you sure it's 1 and not true?
this.$set(this, 'form', form);
}
},
mounted() {
console.log(this.form)
setTimeout(this.update, 1000)
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.8/vue.min.js"></script>
<div id="app">
<div class="form-group">
<h5>Publish:</h5>
<label class="radio-inline">
<input type="radio" name="publish" class="styled" value="1" v-model="form.publish">
Yes
</label>
<label class="radio-inline">
<input type="radio" name="publish" class="styled" value="0" v-model="form.publish">
No
</label>
</div>
</div>
okay my bad.... it is not a problem with vue.js but instead because i am using uniform.js for my radio button styling from admin template that i bought in themeforest and they don't provide a clear documentation...
and after searching around i find that the javascript and css that style my radiobutton is by uniform.js and i just add a jquery code to run update the radiobutton
I have wasted few hours, and later got to know, I was missing :checked="item.isActive == true" property while binding. Adding this worked for me.
<input
class="form-check-input"
type="radio"
name="students"
v-model="item.isActive"
:checked="item.isActive== true">

React controlled radio buttons not being checked

I have a child component that receives props from a parent. In the child component it renders a couple radio buttons like this:
<div>
<div className="radio">
<label>
<input
type="radio"
name="value"
onChange={this._handleInputChange}
value="1"
checked={this.props.value === "1"}
/>
True
</label>
</div>
<div className="radio">
<label>
<input
type="radio"
name="value"
onChange={this._handleInputChange}
value="0"
checked={this.props.value === "0"}
/>
False
</label>
</div>
</div>
handleInputChange just calls a parent method like so:
_handleInputChange(e) {
this.props.handleChange(e);
}
that will set the state of the parent component to the value selected in the radio buttons (i.e. "1" or "0"). The issue im having is that the checked conditionals return the correct props, but they function strangely. It almost seems like when the radio input receives a new prop value, it doesn't re render with checked. When the component first renders, the props.value is an empty string. When a user selects a radio button it changes the state of the parent component with _handleInputChange and then sends that value back down for the conditionals.
Thanks to some of the help here and on IRC I figured out it was a preventDefault in my event handler. After removing that it worked perfectly!
You must use state for checked property if you want react re-render radio button.
Example:
<div>
<div className="radio">
<label>
<input
type="radio"
name="value"
onChange={this._handleInputChange}
value="1"
checked={this.state.radioButton1}
/>
True
</label>
</div>
<div className="radio">
<label>
<input
type="radio"
name="value"
onChange={this._handleInputChange}
value="0"
checked={this.state.radioButton2}
/>
False
</label>
</div>
</div>
You also set value for state like this (alternatively, you can initialize it with getInitialState):
this.setState({
radioButton1 : props.value ==="1",
radioButton2 :props.value ==="0"
});
And in _handleInputChange function you're able to know that radio button is checked or unchecked by checking it's state.
_handleInputChange(e) {
var isChecked = e.target.value ==="1" ? this.state.radioButton1 : this.state.radioButton2;
this.props.handleChange(e);
}
use bind method to bind context this._handleInputChange.bind(this) in the constructor,or use (e)=>this._handleInputChange(e) on click ,when the event handler executed normally has no context.
or declared as this below,it can bind this automatically:
class ButtonGroup extends Component{
....
_handleInputChange= (e)=>{
...
}
sample below:
class ButtonGroup extends Component {
render() {
return (
<div>
<div className="radio">
<label>
<input
type="radio"
name="value"
onChange={(e) => this._handleInputChange(e)}
value="1"
checked={this.props.value === "1"}
/>
True
</label>
</div>
<div className="radio">
<label>
<input
type="radio"
name="value"
onChange={(e) => this._handleInputChange(e)}
value="0"
checked={this.props.value === "0"}
/>
False
</label>
</div>
</div>
);
}
_handleInputChange(e) {
this.props.handleChange(e);
}
}
class Form extends Component {
constructor(props) {
super(props);
this.state = {value: '1'};
}
render() {
var value = this.state.value;
return <ButtonGroup value={value} handleChange={(e) => this.valueChanged(e)}/>
}
valueChanged(e) {
this.setState({value: e.target.value});
}
}
ReactDOM.render(
<Form />,
document.getElementById('container')
);

Categories

Resources