Clickable option with action in select - vue.js

I'm working on a Vue file and have a select
<select v-if="show">
<option v-on:click="test()" value=""> someData</option>
<option>otherdata</option>
</select>
[...]
var instance = new Vue({
el: "#General",
[...]
methods:{
test: function(){
alert('youre goddam right');
}
[...]
}
[...]
}
So What i'm trying to do is to display my datas someData and otherdata. That works great but what i want it's when the user click on firstData, the action "test" append, and an alert comes up but that doesn't work here. I tried with the v-on:click but nothing happend.
Thanks for the help

Yes so it appears that the click event is not triggered for an <option> element. Here is one of the many fix available: using the input event on the select instead, and filter the value.
var instance = new Vue({
el: "#General",
methods:{
test: function(value) {
if (value === "choice1") {
alert('youre goddam right');
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.js"></script>
<div id="General">
<select v-on:input="test($event.target.value)">
<option value="choice1">someData</option>
<option>otherdata</option>
</select>
</div>

Related

How can I defined as Default checked in a checkbox with Vuejs

I have tried all that I have read in other questions and they did not answer me the problem.
I have a checkbox like this in a list
<input type="checkbox" v-model="selected" :value="post.rut">
I have the model defined like this:
data: function() {
return {
selected: []
}
}
The problem is that If I add checked as default.. it does not change at all I mean it keeps the checkbox not checked
<input type="checkbox" v-model="selected" :value="post.rut" checked>
If I remove the v-model, it works BUT I can not send the value to the controller because I need the v-model to bind so I wonder how can I set as default checked in that checkbox input like that?
Thanks
you have the input value as post.rut you can put it in selected array in data like :
data: function() {
return {
selected: [this.post.rut]
}
}
If you already know which field you want to selected based on the post you can do like so:
data: function() {
return {
selected: [this.post.rut]
Here is a working example of what you asked for.
Note: You need not use v-model and :value at the same time since v-model itself is a two way binder.
var app = new Vue({
el: '#app',
data() {
return {
selected: true
};
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input type="checkbox" v-model="selected"/>
</div>

VueJS Using #click on <option> elements and #change on <select> element

I have a simple function that manipulates a data between true and false. I use it to make my div hidden and visible like a toggle. I also have a with three element. I found out that I cannot use #click for <option> elements, I need to use #change for my <select>.
But in this way, whenever an is selected, the function is being triggered and my data toggles between true and false. Here is my <select> element;
<select #change="isDisabled">
<option>Please select a security type</option>
<option>No Security</option>
<option>Personal</option>
<option>Enterprise</option>
</select>
IsDisabled function takes a variable and change its values between true and false so my div becomes hidden and visible as follows;
<div v-if="noSecurity">something</div>
But here is the thing, I only want to trigger the function when the user select the "No Security" option. Now it's being triggered whenever I select an option, so it turned out to be some kind of a toggle. But I want to hide the div when I select the "No Security" option and show the div if something different is selected. What should I do?
I've made a CodeSandbox where you could see the result :
https://codesandbox.io/s/magical-meitner-63eno?file=/src/App.vue
But here is the explanation:
<template>
<section>
<select #change="isDisabled">
<option>Please select a security type</option>
<option>No Security</option>
<option>Personal</option>
<option>Enterprise</option>
</select>
<div v-if="noSecurity">You Choose no security, that's dangerous !</div>
</section>
</template>
<script>
import HelloWorld from "./components/HelloWorld";
export default {
name: "App",
data() {
return {
noSecurity: false,
};
},
methods: {
isDisabled(e) {
console.log("e", e.target.value);
if (e.target.value === "No Security") {
// do your change
return (this.noSecurity = !this.noSecurity);
}
// to allow reset if another option is selected
if (this.noSecurity) {
return this.noSecurity = false;
}
},
},
};
</script>
Basically when you use the #change handler, your function will receive an event, in this event you can catch the target value with event.target.value.
Doing so, you do a condition if the value is equal to No Security (so the selected item), you change your state, if it's not No Security, you do nothing, or you do something else you would like to do.
Appart from that, I advice you to change your method name isDisabled to a global convention name like handleChange, or onChange.
Pass id values in your option so when you get the select event you're clear that No security or whatver the name you would like to change will be the same.
Because if one day you change No security to another name, you have to update all your conditions in your app. Try to avoid conditions with strings values like this if you can.
<option value="1">No Security</option> // :value="securityType.Id" for example if coming from your database
<option value="2">Personal</option>
<option value="3">Enterprise</option>
then in your function it will be
if (e.target.value === noSecurityId) {
// do your change
this.noSecurity = !this.noSecurity;
}
//...
There's no need for the additional noSecurity variable. Create your select with v-model to track the selected value. Give each option a value attribute.
<select v-model="selected">
<option value="">Please select a security type</option>
<option value="none">No Security</option>
<option value="personal">Personal</option>
<option value="enterprise">Enterprise</option>
</select>
Check that value:
<div v-if="selected === 'none'">something</div>
You can still use the noSecurity check if you prefer by creating a computed:
computed: {
noSecurity() {
return this.selected === 'none';
}
}
Here's a demo showing both:
new Vue({
el: "#app",
data() {
return {
selected: ''
}
},
computed: {
noSecurity() {
return this.selected === 'none';
}
},
methods: {},
created() {}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<select v-model="selected">
<option value="">Please select a security type</option>
<option value="none">No Security</option>
<option value="personal">Personal</option>
<option value="enterprise">Enterprise</option>
</select>
<div v-if="selected === 'none'">something</div>
<div v-if="noSecurity">something</div>
</div>
Is using v-model instead of using a method is option for you? If it is, please try the following:
HTML:
<div id="hello-vue" class="demo">
<select v-model="security">
<option>Please select a security type</option>
<option>No Security</option>
<option>Personal</option>
<option>Enterprise</option>
</select>
<div v-if="security=='No Security'">something</div>
</div>
JS:
const HelloVueApp = {
data() {
return {
security: undefined
}
}
}

How to resolve error of function do not called after selecting from the select list?

I want to call a function for date range can call the function by selecting particular options from the select list after selecting particular option regarding it, particular function must get a call and should fetch record ????
I'm trying it by using onChange() but it wont work. How to resolve it?
Within the onChange method you put your own logic for the date range
new Vue({
el: "#app",
data: {
key: ""
},
methods: {
onChange() {
console.log(this.key)
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<select name="LeaveType" #change="onChange()" class="form-control" v-model="key">
<option value="1">Annual Leave/ Off-Day</option>
<option value="2">On Demand Leave</option>
</select>
</div>

Vue.js Checkbox issue in Firefox, works file in Chrome and IE

I am using a checkbox.
<template v-for="(item,index) in items">
<div >
<input type="checkbox"
v-model="item.checked"
#click="selectionCheckboxClicked(index,item.checked)"
/>
</div>
.....
And this is the JS code
selectionCheckboxClicked: function selectionCheckboxClicked(index,checked) {
console.log(this.items[index].checked);
console.log(checked);
....
},
Initial value of item.checked is false. When I click the checkbox in Chrome or IE, it checks the checkbox and displays 'true' in console log. However, when I run the code in Firefox, though it does change the state, console log displays false in selectionCheckboxClicked(). I need to take some action based on the current state of the checkbox in selectionCheckboxClicked(), which I ma finding difficult to implement in the current situation.
Shall appreciate any suggestions to fix the issue.
Because for checkbox, v-model bind #change not #input (check Vue Github: source codes for v-model). Then #change will be fired after lose focus.
But you should not rely on the order either #click or #change will be executed first (check this answer for more details).
So one solution is uses #change=handler($event) instead, because v-model uses addHandler with one parameter named important=true to make sure it will be fired first than your event handler.
new Vue({
el: '#app',
data() {
return {
testValues: false
}
},
methods: {
selectionCheckboxClicked: function(ev) {
console.log(this.testValues);
console.log(ev.target.checked);
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
<div>
<input type="checkbox" v-model="testValues" #change="selectionCheckboxClicked($event)" />
</div>
</div>
Or another solution is uses #input but you should rely on what is checked or not on the input Dom element.
new Vue({
el: '#app',
data() {
return {
testValues: false
}
},
methods: {
selectionCheckboxClicked: function(ev) {
console.log('v-model:', this.testValues);
console.log('inputCheckedAtDom:', ev.target.checked);
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
<div>
<input type="checkbox" v-model="testValues" #input="selectionCheckboxClicked($event)" />
</div>
</div>
If you still like to use #click, one solution actually is same as #input. Uses one ref to access the input Dom element.
new Vue({
el: '#app',
data() {
return {
testValues: false
}
},
methods: {
selectionCheckboxClicked: function(ev) {
console.log('v-model:', this.testValues);
console.log('inputCheckedAtDom:', this.$refs.test.checked);
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
<div>
<input ref="test" type="checkbox" v-model="testValues" #click="selectionCheckboxClicked($event)" />
</div>
</div>
setTimeout will work because it will be executed after current task finished and re-render. Even you uses setTimeout(()=>{}, 0)(delay 0 seconds), it will still work.
What seems to be happening is that Firefox calls the click function immediately even before the v-model = "item.checked" has changes. When I check the value of this.items[index].checked after some delay (say 100 ms), it displays true.
console.log(this.items[index].checked);
console.log(checked);
var self = this;
setTimeout(function()
{ if (self.items[index].checked)
self.selectedContactsCount++;
else
self.selectedContactsCount--;
},
100);

Change options and value at the same time

I have a problem when I try to change the options of my select and its value at the same time. If I use v-model, it works properly but if I use v-bind:value + v-on:change, it will not work.
Here is a js fiddle that will illustrate the problem : https://jsfiddle.net/2vcer6dz/18/
The first time you click on the button "change", only the first select value will be 3. If you reclick they all become 3.
Html
<div id="app">
<select v-model="value">
<option v-for="item in options" :key="item.Value" :value="item.Value">{{item.Text}}</option>
</select>
<select :value="value" v-on:change="value = $event.target.value">
<option v-for="item in options" :key="item.Value" :value="item.Value">{{item.Text}}</option>
</select>
<select-option v-model="value" :options="options"></select-option>
<br />
<input type="button" value="change" v-on:click="change" />
</div>
<template id="template-select-option">
<select :value="value" v-on:change="update($event.target.value)">
<option v-for="item in options" :key="item.Value" :value="item.Value">{{item.Text}}</option>
</select>
</template>
Javascript
Vue.component('select-option', {
template: '#template-select-option',
props: ['value', 'options'],
methods: {
update: function (value) {
this.$emit('input', value);
}
}
});
new Vue({
el: '#app',
data: {
value: 1,
options: [{Value:1, Text:1}, {Value:2, Text:2}]
},
methods: {
change: function () {
this.options = [{Value:1, Text:1}, {Value:2, Text:2}, {Value:3, Text:3}];
this.value = 3;
}
}
});
Expected result
All selects should have the value "3" when you click on the button "change"
Changing the options and the value at the same time is confusing Vue. This is probably a minor bug in Vue. If you use $nextTick to push the value change off to the next update cycle, they all work.
change: function () {
this.options = [{Value:1, Text:1}, {Value:2, Text:2}, {Value:3, Text:3}];
this.$nextTick(() => {
this.value = 3;
});
}
It seems that this is a known bug which was closed because a workaround was found.
The workaround is to declare another property and cast v-model on it. This solutions is easier to implement inside a component.
https://jsfiddle.net/6gbfhuhn/8/
Html
<template id="template-select-option">
<select v-model="innerValue">
<option v-for="item in options" :key="item.Value" :value="item.Value">{{item.Text}}</option>
</select>
</template>
Javascript
Vue.component('select-option', {
template: '#template-select-option',
props: ['value', 'options'],
computed: {
innerValue: {
get: function() { return this.value; },
set: function(newValue) { this.$emit('input', newValue); }
}
}
});
Note: In the github thread, it is suggested to use a computed property instead, but if you use a computed property, vue will throw warning every time you change the value in your dropdown because computed property don't have setter.