I have a select where I am trying to set the :selected value to data from my server on page load. All the data is accessible but I am not sure what I am missing. My prop customer is an object that is passed in from the parent and comes from the backend. The value of customer.state is the abbreviated state , so "CA" for example. I tried doing :selected="this.customer.state" but that didn't work either.
data() {
return {
this.states = [
{text: "California", value: "CA"},
{text: "New Jersey", value: "NJ"},
//etc
],
}
},
props: {
customer: {type: Object}
}
<select name="state" autocomplete="address-level1" #change="optionDropdown">
<option v-for="x in optionsReturned" :value="x.value" :selected="???">
{{ x.text }}
</option>
</select>
value of selected must be true when the currently looped option is equal to customer's state (and false otherwise): :selected="customer.state === x.value"
Related
So i'm working with you and I have a select component, I created a modelValue prop which is an empty string, and passed it in v-model:
<select v-model="modelValue" #change="changeOption">
<option
disabled
value="">
Choose from the list
</option>
<option
v-for="option in options"
:key="option.value"
:value="option.value">
{{ option.name }}
</option>
</select>
props:{
modelValue:{
type: String
},
options:{
type: Array,
default: () => []
}
}
But for some reason it gives an error: Unexpected mutation of "modelValue" prop.
I just started working with Vue so I'm not sure where this error could come from. I was following a tutorial and everything seemed to work there.
You can't modify a prop directly.
The best way is create a computed with get set functions and emit update inside set function.
https://v2.vuejs.org/v2/guide/computed.html#Computed-Setter
computed: {
localModelValue: {
get() {
return this.modelValue
},
set(newValue) {
this.$emit('update:modelValue', newValue)
},
},
},
And in the component instance declare prop as sync
https://v2.vuejs.org/v2/guide/components-custom-events.html#sync-Modifier
:model-value.sync="..."
create life cycle "computed"
computed: {
localModelValue: {
get() {
return this.modelValue
},
},
},
After that change v-model="modelValue" to v-model="localModelValue"
I have a dropdown list containing document types, in which I need the selected type to be stored in a data property, specifically the type.name , so I can reference it in a child component. However, my choice is not being stored. Am I going about this wrong?
Expected Result: type.name is available to me in a data variable.
<b-select
:v-model="documentType" >
<option
v-for="type in group.documentTypes"
:key="type.id"
:value="type.id"
:v-model="selected"
>
{{(type.name)}}
</option>
</b-select>
data() {
return {
waiting: {},
timer: null,
selected: ''
}
},
Just put your v-model on your select-tag. With an input-event you can pass your selection to methods.
UPDATE FROM HERE: There you can work with the name you've selected and pass it to your child.vue or do whatever you want.
But be aware - don't write :v-model it's only v-model !
CODE
TEMPLATE
<select v-model="selected_DT" #input="storeSelect(selected_DT)>
<option v-for="type in documentTypes" :key="type.id">
{{type.name}}
</option>
</select>
SCRIPT:
data() {
return {
selected_DT: null,
documentTypes: [
{"id": 1, "name": "Test1"},
{"id": 2, "name": "Test2"},
{"id": 3, "name": "Test3"},
]
}
},
methods: {
storeSelect(selected_DT) {
console.log(selected_DT) //it's selected name you can pass to your child.vue
}
},
You are very close but your v-model needs to be placed on your select html element. Then when one of the options are selected the value of the option will be passed to it
<select v-model="selected">
<option
v-for="type in group.documentTypes"
:key="type.id"
:value="type.id">
{{type.name}}
</option>
</select>
I'm new to Vue.js (using Nuxt.js) and what I'm trying to achieve is to have a Select component that I can reuse everywhere and is W3C compliant.
With the help of #Jasmonate answers, I managed to create this component, it's working. But the value attribute is still visible in the source code and so isn't W3C compliant. Maybe the problem is coming from somewhere else in the project ?!
Parent component
<custom-select
:options="options"
v-model="selectedOption"
></custom-select>
<span>Selected : {{ selectedOption }}</span>
<script>
data() {
return {
selectedOption: "A",
options: [
{ label: "One", value: "A" },
{ label: "Two", value: "B" },
{ label: "Three", value: "C" }
],
};
}
</script>
custom-select.vue
<template>
<select :value="value" #input="clicked">
<option
v-for="option in options"
:key="option.label"
:value="option.value"
>
{{ option.label }}
</option>
</select>
</template>
<script>
export default {
props: {
value: {
required: true
},
options: {
type: Array,
required: true
}
},
methods: {
clicked($event) {
this.$emit("input", $event.target.value);
}
}
};
</script>
I read those documentation pages:
Form Input Bindings
Components Basics
And also looked around the web to find example of v-model in a custom component, but it's always about the input tag. The only example I found about a custom select with v-model isn't actually a select tag, like the Vue Select plugin or this thread on StackOverflow.
v-model is syntax sugar. By default, the value is a prop that has the name value, and it changes (two-way-binding) whenever the event input is emitted.
Also, v-model is bound on the select element, not option.
Your code can be modified as such:
<template>
<select :value="value" #input="clicked">
<option
v-for="option in options"
:key="option.label"
:value="option.value"
>
{{ option.label }}
</option>
</select>
</template>
<script>
export default {
props: {
value: {
required: true
},
options: {
type: Array,
required: true
}
},
methods: {
clicked($event) {
this.$emit('input', $event.target.value);
}
}
};
</script>
Documentation here: https://v2.vuejs.org/v2/guide/components.html#Using-v-model-on-Components
You can also change the prop name and event name that v-model uses, see: https://v2.vuejs.org/v2/guide/components-custom-events.html#Customizing-Component-v-model
I have to create a dynamic form in vue2. I want to save the values of the dynamic fields in an named object so that I can pass them along on submit.
The following code is working fine except I get an error in the console when I change the input value the first time (value will be propagated correctly though):
[TypeError: Cannot read property '_withTask' of undefined]
Here is how I define the props:
props: {
fields: {
type: Object,
default: {startWord: 'abc'}
},
},
And this is how I populate the model from the input field:
v-model="fields[field.id]"
Here is the entire code:
<template>
<div>
<!-- Render dynamic form -->
<div v-for="(field, key) in actionStore.currentAction.manifest.input.fields">
<!-- Text -->
<template v-if="field.type == 'string'">
<label>
<span>{{key}} {{field.label}}</span>
<input type="text" v-bind:placeholder="field.placeholder"
v-model="fields[field.id]"/>
</label>
</template>
<!-- Footer -->
<footer class="buttons">
<button uxp-variant="cta" v-on:click="done">Done</button>
</footer>
</div>
</template>
<script>
const Vue = require("vue").default;
const {Bus, Notifications} = require('../../Bus.js');
module.exports = {
props: {
fields: {
type: Object,
default: {startWord: 'abc'}
},
},
computed: {
actionStore() {
return this.$store.state.action;
},
},
methods: {
done() {
console.log('fields', this.fields);
Bus.$emit(Notifications.ACTION_INPUT_DONE, {input: this.fields});
}
},
}
</script>
So again, everything is working just fine (showing initial value in input, propagating the new values to the model etc.). But I get this '_withTask' error when I first enter a new character (literally only on the first keystroke). After that initial error it doesn't pop up again.
-- Appendix --
This is what the manifest/fields look like:
manifest.input = {
fields: [
{ id: 'startWord', type: 'string', label: 'Start word', placeholder: 'Enter start word here...' },
{ id: 'startWordDummy', type: 'string', label: 'Start word dummy', placeholder: 'Enter start word here...' },
{ id: 'wordCount', type: 'integer', label: 'Word count' },
{ id: 'clean', type: 'checkbox', label: 'Clean up before' },
]
}
-- Update --
I just discovered that if I set the dynamic field values initially with static values I don't get the error for those fields set this way:
created() {
this.fields.startWord = 'abc1';
},
But this is not an option since it will be a dynamic list of fields. So what is the best way to handle scenarios like this?
From documentation: Due to the limitations of modern JavaScript (and the abandonment of Object.observe), Vue cannot detect property addition or deletion. Since Vue performs the getter/setter conversion process during instance initialization, a property must be present in the data object in order for Vue to convert it and make it reactive.
As I understand it's bad idea create keys of your object by v-model.
What would I do in HTML:
<input type="text"
:placeholder="field.placeholder"
#input="inputHandler(event, field.id)" />
Then in JS:
methods: {
// ...
inputHandler({ target }, field) {
this.fields[field] = target.value;
}
},
I have a select element within a vue component that looks like this:
<template>
<select v-model="item.value" >
<option value="1">A</option>
<option value="2">B</option>
</select>
<div>
You selected {{item.text}} with a value of {{item.value}}
<div>
</template>
<script>
export default {
data() {
return {
item: {
text: '',
value: 0
}
}
}
}
</script>
If I make a selection, on A, I get a value of 1, if I make a selection on B. I get a value of 2. So item.value will be populated. How do I fill up item.text?
If I remove the value attribute from the options, I get the answer, but now my value wouldn't be populated.
I'd recommend using an array of objects that hold both the value and text for each <option>. For example
data() {
return {
// ...
options: [
{ value: 1, text: 'A' },
{ value: 2, text: 'B' }
]
}
}
Then you can use a v-for to iterate this list and simply bind the selected item with v-model
<select v-model="item">
<option v-for="opt in options" :key="opt.value" :value="opt">
{{opt.text}}
</option>
</select>
See https://v2.vuejs.org/v2/guide/forms.html#Select-Options