Vue JS - Display option 2 of select menu after it is disabled - vue.js

I am looking for help on how to display the second option in a select drop-down menu after the select menu is disabled.
It is disabled if there are fewer than 2 options left. The first option is the 'Please select' option but I would like it to display the one remaining option which is the second option. i.e. 'Scotland' in the code below. The data is pulled in using an Axios call so I do not know what the value will be.
Any help would be greatly appreciated.
The select menu code
<select disabled="disabled">
<option disabled="disabled" value="">Select nationality</option>
<option value="Scotland"> Scotland </option>
</select>
Vue
computed: {
selectDisabled: function() {
return this.options.length <= 2;
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<select v-model="quantity" :disabled="selectDisabled">
<option disabled value="">Select</option>
<option v-for="option in options" :value="option">{{option}}</option>
</select>
</div>

You need to create a special computed property that will dynamically tell the <select> which option it should show inside itself. <select> show the option that matches the <select>'s value.
So:
When the select is disabled (has less than 2 options) force it's value to be the value of the first listed option (this.options[0]).
When the select is enabled, pass the normal value selected by the user (this.value)
I've implemented the logic you need below (make sure to click "Run snippet"):
const App = {
el: '#app',
template: `
<div>
<!--
Remember that writing v-model="quantity" is the same as writing :value="quantity" #input="quantity = $event"
(or #input="quanity = $event.target.value" if you put in HTML elements)
You can't use v-model="valueFormatted" here because this would be the same as writing
:value="valueFormatted" #input="valueFormatted = $event.target.value"
So that's a mistake, because valueFormatted is a computed and you can't assign to it
(unless you create a special computed with a setter, but that's not what you need right now)
-->
<select :value="valueFormatted" #input="value = $event.target.value" :disabled="disabled">
<option disabled="disabled" value="">Select nationality</option>
<option v-for="option in options" :value="option">{{option}}</option>
</select>
<hr>
<div>
<button #click="options = ['Scotland']">Make the select have 1 item</button>
<button #click="options = ['Scotland', 'Poland']">Make the seelct have 2 items</button>
</div>
</div>
`,
data() {
return {
options: ["Scotland", "Poland"],
value: '',
}
},
computed: {
disabled() {
return this.options.length < 2
},
/*
* If this.disabled is true, returns the value of the first option
* If it's false, it returns the normal value from data (user selected)
*/
valueFormatted() {
//watch out - this computed will return undefined if this.disabled is true and if options is empty
//to avoid that, you can do for example this:
//return this.disabled === true ? (this.options[0] ?? '' ) : this.value;
return this.disabled === true ? this.options[0] : this.value;
},
},
}
new Vue(App);
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<html>
<body>
<div id="app" />
</body>
</html>
You're probably going to use this select's value later to make eg. an API call, so make sure to send this.valueFormatted instead of this.value

Related

Show/hide next input field based on dropdown selection

I am new to Vue.js. I want to know how to show next input field based on previous dropdown menu selection. I have checked other forums and tried to implement but that didn't work.
Here is my code:
<select v-model="receive_method" id="">
<option value="cheque">Cheque</option>
<option value="eftn">EFTN</option>
<option value="cash">CASH</option>
</select>
<div v-if="receive_method === 'Cheque' ">
<input type="integer" v-model="cheque_number" placeholder="Cheque Number">
</div>
If I select cheque option from the dropdown list the next input field will appear else it will remain hidden.
Please help.
You need to reference the value of the options element.
If value="cheque" is lowercase, v-if="receive_method === 'cheque'" should too.
This works:
<script setup>
import { ref } from 'vue'
const receive_method = ref()
const cheque_number = ref()
</script>
<template>
<select v-model="receive_method" id="">
<option value="cheque">Cheque</option>
<option value="eftn">EFTN</option>
<option value="cash">CASH</option>
</select>
<div v-if="receive_method === 'cheque'">
<input type="integer" v-model="cheque_number" placeholder="Cheque Number">
</div>
</template>
If using Options API
<script>
export default {
data() {
return {
receive_method: undefined,
cheque_number: undefined
}
}
}
</script>

Vue.js Change previuos value back to default when switching between options

I have an dropdown with multiple options.All options has display variable .By default it is set to available .If i select an option the display value changes to assigned name..I would like to change the previous selected display value back to available when i switch between options.
<div>
<label class="label">Student Name</label>
</div>
<div>
<select class="input"
:class="{ 'placeholder': studentNameInput === 0 }"
v-model="studentNameInput"
#change= "verify('studentName')">
<option v-for="(student, index) in students"
v-if="student.display=== 'available' || student.display === 'studentName'"
:key="index"
:value="index">
{{ student.name }}
</option>
</select>
</div>
**Method**
verify(val){
if (val === 'studentName') {
this.studentName = this.students[this.studentNameInput].id;
this.students[this.studentNameInput].display = 'studentName';
}
}
You can use a watcher on your v-model to retrieve the oldValue and set it's display to available when switching to a newValue
watch: {
studentNameInput: function (newValue, oldValue) {
this.students[oldValue].display = 'available'
}
}

Vue selected option

I am trying to change the selected option on page load. When the page is loaded and new or used is not null the I want which ever on that is not null to be selected instead of it alway selecting status. I have tried many things and nothing has worked and have not been able to fin much online about how to make this work.
I have tried it with and without v-bind, without v-model, and other ways that I saw online.
<select id="application-status" class="custom-select" v-model="selected">
<option :value="null" disabled>Status</option>
<option :value="'new'" v-bind:selected="item.new != null">New</option>
<option :value="'used'" v-bind:selected="item.used != null">Used</option>
</select>
Right no no matter what Status always shows up.
You need to set the value of selected in some manner. One way is, as Sphinx pointed out in their comment, is to use a mounted() lifecycle hook:
const app = new Vue({
el: "#app",
mounted() {
this.selected = "used";
},
data() {
return {
selected: "",
item: "new"
};
}
});
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.min.js"></script>
<div id="app">
<select id="application-status" class="custom-select" v-model="selected">
<option :value="null" disabled>Status</option>
<option :value="'new'" v-bind:selected="item.new != null">New</option>
<option :value="'used'" v-bind:selected="item.used != null">Used</option>
</select>
</div>

remove option from second select if already selected [Ordered multiple selection]

I had select option repeater.
What I want is that when I selected johndoe at the first option, it will no longer display on the second select option.
here's my html
<div id="app">
<h1>Vue JS Multiple Fields Repeater</h1>
<div class="col-sm-6">
<div class="panel panel-default relative has-absolute" v-for="(field, index) in users.usersRepeater">
<button #click="addUsersField" type="button">
Add
</button>
<button #click="deleteUsersField(index)" v-if="field != 0" type="button">
Delete
</button>
<div class="panel-body has-absolute">
<div class="form-group">
<label for="users" class="control-label col-sm-3 text-left">Users {{field}}</label>
<select :name="'users'+index"
class="form-control"
id="users">
<option value="" hidden>Select User</option>
<option value="1">John Doe</option>
<option value="2">Mark Doe</option>
<option value="3">Mae Doe</option>
<option value="4">John Smith</option>
<option value="5">Mae Smith</option>
</select>
</div>
</div>
</div>
</div>
</div>
here's my vue.js
new Vue({
el: '#app',
data: {
users: {
usersRepeater: [{ user: '' }]
}
},
methods: {
addUsersField: function() {
this.users.usersRepeater.push({
user: ''
});
},
deleteUsersField: function(index) {
this.users.usersRepeater.splice(index, 1);
},
}
});
here's the fiddle -> https://jsfiddle.net/0e3csn5y/23/
Ok I have this working now. I liked the question because making an ordered selection is a generic case. But, for me anyway, it wasn't straightforward. The breakthrough was realising that, when you number the choices, the whole state of the component could be encapsulated in one array, allUsers. Available users and choices then become computed properties, based on this array. Moral of the story: get your store right, with no interactions between elements of the store.
My answer weighs in at 130 lines. How long and hard would this be without Vue? Mind boggles.
Stack wants me to post some code, so here's the computed property that generates an array of choices made, in order of their priority, from the all users array...
choices(){
return this.store.allUsers.map((aUser,index)=>{
if(aUser.selection != null)
return {idxAllUsers : index, selection: aUser.selection};
else
return null;
})
.filter(aSelection=>aSelection != null)
.sort((a,b)=>{return a.selection - b.selection})
.map(a=>a.idxAllUsers);
},
I found this one very helpful.

v-model variable return whole select instead of its value

I want to get value from select tag. So I bind a variable with v-model like below.
HTML:
<div id="action_panel">
<select id="work_type" v-model="type">
<option value="" disabled selected></option>
<option value="1">A</option>
<option value="2">B</option>
</select>
<div>
JS:
var vm = new Vue({
el: '#action_panel',
data: {},
methods: {
addWorks: function(emp_id) {
console.log(type);
}
}
});
console.log() returns the whole html entity of select tag.
I got no clues on vue.js doc.
The type variable is never declared. You should declare it as data of your application before using it.
https://jsfiddle.net/gurghet/mwy5uLb4/