Set selected value with v-model with vuex-store - javascript

I have the following select dropdown in Vue.js -2
<p-grid-item v-if="isOption">
<div class="form-field required selectbox">
<span class="region-dd-icon icon-sf-dropdown"></span>
<label class="move-label">{{ $t("region") }}</label>
<select name="region" id="region" label="region" v-validate="'required'" v-model="region" class="input required selectbox region" data-vv-scope="userDetails" aria-label="Region" #change="regionChange()">
<option value="">{{ $t("region") }}</option>
<p-option v-for="regionOption in regionList" :key="regionOption.region" :value="regionOption.plane">{{$t(regionOption.region)}}</p-option>
</select>
</div>
<p class="small-txt-info" v-html="$t('regionInfo')"></p>
</p-grid-item>
I am getting the regionList from the configuration file and using the following code for it.
In the configuration file I have :
regions :[
{'region': 'US', plane: 'US_STAGING'},
{'region': 'EU', plane: 'EU_STAGING'}
]
and in the component
mounted () {
this.isOption = this.$route.query.plan === 'myPlan'
if (this.isOption) {
this.regionList = config[process.env.NODE_ENV].regions
this.$store.dispatch('updateRegionList', this.regionList)
}
}
In the store.js file, I have
const store = new Vuex.Store({
state: initState(),
mutations: {
setRegionList: function (state, regionList) {
state.regionList = regionList
}
},
actions: {
updateRegionList: function (context, regionList) {
context.commit('setRegionList', regionList)
}
}
}
Now I am trying to make the first value of the select as selected by default and so trying to set value for region as it is mentioned as v-model. I am using the following code :
created () {
this.region = this.regionList[0]
}
[__ob__: Observer]
length
:
0
__ob__
:
Observer {value: Array(0), dep: Dep, vmCount: 0}
[[Prototype]]
:
Array
How can I set the default value for my select box ? I am new to Vue and so any help will be appreciated.

Related

Set first value in dropdown as default value in VueJs

I want to make the first value of time Object as a default value for my dropdown. Whenever user enter the website, the first value has been selected as my default value. However, my current code only display the value but not selected yet on vue data. How can I do that?
time Object:-
{ "1290_1320":"21:30 - 22:00",
"1320_1350":"22:00 - 22:30",
"1350_1380":"22:30 - 23:00"
}
Dropdown HTML:-
<div class="form-group col-md-8">
<select id="pickup" class="form-control" #change.prevent="changeTime($event)">
<option selected="selected" v-for="(time, i) in this.timeslots" :key="i"
:value="time">{{time}}</option>
</select>
</div>
Vue:-
export default {
data() {
return {
selectedTime: null
}
},
methods: {
changeTime(event) {
this.selectedTime = event.target.options[event.target.options.selectedIndex].text;
}
Dropdown javascript:-
// remove "selected" from any options that might already be selected
$('#pickup option[selected="selected"]').each(
function() {
$(this).removeAttr('selected');
}
);
// mark the first option as selected
$("#pickup option:first").attr('selected','selected');
It depends on your particular usecase but generally you can do something like this:
<div class="form-group col-md-8">
<select id="pickup" v-model="selectedTime" class="form-control">
<option v-for="(timeValue, timeID) in timeslots" :key="timeID" :value="timeID">{{ timeValue }}</option>
</select>
</div>
<script>
import axios from 'axios';
export default
{
name: 'MyDropDown',
data()
{
return {
selectedTime: null,
timeSlots: {},
}
},
created()
{
this.fetchData();
},
methods:
{
fetchData()
{
axios.get('/api/getTimeSlots').then(response =>
{
this.timeSlots = response.data;
this.selectedTime = Object.keys(response.data)[0];
});
},
}
}

Laravel can't get the values from Vue-multiselect

I am using Vue-multiselect with Laravel.
I am using the multiselect component in my form to let the user select multiple countries. The component works fine but when I submit the form and I dd() it, it shows [object Object].
I can't get the value of the multiselect component. I have found similar questions but none of them worked for me.
Here is my code:
The ExampleComponent.vue file:
<template slot-scope="{ option }">
<div>
<label class="typo__label">Restricted country</label>
<multiselect
v-model="internalValue"
tag-placeholder="Add restricted country"
placeholder="Search or add a country"
label="name"
name="selectedcountries[]"
:options="options"
:multiple="true"
track-by="name"
:taggable="true"
#tag="addTag"
>
</multiselect>
<pre class="language-json"><code>{{ internalValue }}</code></pre>
</div>
</template>
<script>
import Multiselect from 'vue-multiselect'
// register globally
Vue.component('multiselect', Multiselect)
export default {
components: {
Multiselect
},
props: ['value'],
data () {
return {
internalValue: this.value,
options: [
{ name: 'Hungary' },
{ name: 'USA' },
{ name: 'China' }
]
}
},
watch: {
internalValue(v){
this.$emit('input', v);
}
},
methods: {
addTag (newTag) {
const tag = {
name: newTag,
code: newTag.substring(0, 2) + Math.floor((Math.random() * 10000000))
}
this.options.push(tag)
this.value.push(tag)
}
},
}
</script>
Here is my register form:
<div id="select">
<example-component v-model="selectedValue"></example-component>
<input type="hidden" name="countriespost" :value="selectedValue">
</div>
<script>
const select = new Vue({
el: '#select',
data: {
selectedValue: null
},
});
</script>
When I submit the form, the countriespost shows me me this: [object Object] instead of the actual value.
It's because you are providing an array of objects as options property:
options: [
{ name: 'Hungary' },
{ name: 'USA' },
{ name: 'China' }
]
so the value emited on input is an object.
Try to change the options to following:
options: [ 'Hungary', 'USA', 'China' ]
If you pass an array of objects to the :options prop of the multiselect component, you should submit the form with javascript so you can extract the object ids or whatever you need on the backend and then send them through.
Add a method like this:
submit: function() {
let data = {
objectIds: _.map(this.selectedOptions, option => option.id), //lodash library used here
// whatever other data you need
}
axios.post('/form-submit-url', data).then(r => {
console.log(r);
});
}
Then trigger it with a #click.stop event on your submit button.

Vue 2 - How to select the correct <select> option after the data is fetched from db

I'm using Vue 2 for a small blog project. I have a separate component for post's form and one of the form inputs is a select (for post's category). The select gets populated after the categories are fetched from DB. The component also gets a post object from parent component, that is also fetched from the db (see props: ['post']).
Here's the code:
// HTML
...
<select class="form-control" v-model="post.category_id">
<option
v-for="cat in categories"
v-bind:value="cat.id">
{{ cat.name }}
</option>
</select>
...
// JS
module.exports = {
props: ['post', 'url'],
name: 'postForm',
created: function() {
this.syncCats()
},
methods: {
syncCats: function() {
this.$http.get("/api/categories")
.then(function(res) {
this.categories = res.data
})
}
},
data: function() {
return {
categories: {}
}
}
}
The problem I'm having is that none of the options is selected by default. It looks like this. But when I open the select I see both categories from my db like this.
I want to select the correct (post.category_id == cat.id) value by default. How would I do this?
I've tried <select ... :v-bind:selected="post.category_id == cat.id"> but same happened.
Edit
Okay so now I've tried dumping both post.category_id and cat.id like this:
<div class="form-group">
<label>Category</label>
<select class="form-control" v-model="post.category_id">
<option
v-for="cat in categories"
:value="cat.id"
:selected="cat.id == post.category_id">
{{ cat.name }} {{ cat.id }} {{ post.category_id }}
</option>
</select>
</div>
And the result before I select any option is this - only cat.id gets printed, post.category_id does not. However after I select some option I post.category_id appears as well, like this. Notice how the "1" at the end only appears in 2nd screenshot, after I've selected one of the options, which is the {{ post.category_id }}.
This implies that the post is loaded after the categories and that I should somehow reinitialize the select after it's loaded. How would I do this? For reference this is the parent component that fetches the post.
<template>
<span id="home">
<postForm :post="post" :url="url"></postForm>
</span>
</template>
<script>
var postForm = require('../forms/post.vue')
module.exports = {
name: 'postEdit',
created: function() {
this.$http.get('api/posts/slug/' + this.$route.params.slug)
.then(function(response) {
if(response.status == 200) {
this.post = response.data
this.url = "/api/posts/slug/" + response.data.slug
}
})
},
data: function() {
return {
post: {},
url: ""
}
},
components: {
postForm
}
}
</script>
You'll need to set the selected attribute on the appropriate <option> and adhere to Vue's one-way data flow paradigm.
You can even add some extra usability sugar by disabling the <select> until both the post and categories are loaded...
<select class="form-control"
:disabled="!(post.category_id && categories.length)"
#input="setCategoryId($event.target.value)">
<option v-for="cat in categories"
:value="cat.id"
:selected="cat.id == post.category_id">
{{cat.name}}
</option>
</select>
and
methods: {
setCategoryId(categoryId) {
this.$emit('input', parseInt(categoryId))
}
}
Then, in the Vue instance / component that includes the above one, simply use
<post-form :post="post" :url="url"
v-model="post.category_id"></post-form>
See Components - Form Input Components using Custom Events for more information.
JSFiddle demo ~ https://jsfiddle.net/1oqjojjx/267/
FYI, I'd also initialise categories to an array, not an object...
data () {
return {
categories: []
}
}
You should be able to do something like following:
methods: {
syncCats: function() {
this.$http.get("/api/categories")
.then(function(res) {
this.categories = res.data
if(!this.post.category_id) {
this.post.category_id = this.categories[0].id
}
})
}
},

vue js how to set option value selected

I'm using vue js for my application in select option input..I need to set default value should be selected in the drop down and while on change i would like to call two functions ..
I'm new to vue js..
My Code :
var listingVue = new Vue({
el: '#mountain',
data:{
formVariables: {
country_id: '',
mountain_id: '',
peak_id: ''
},
countrylist:[],
mountainlist:[],
},
ready: function() {
var datas = this.formVariables;
this.getCountry();
},
methods: {
getCountry: function()
{
this.$http.get(baseurl+'/api/v1/device/getCountry',function(response)
{
this.$set('countrylist',response.result);
//alert(jQuery('#country_id').val());
});
},
getMountain: function(country_id)
{
var datas = this.formVariables;
datas.$set('country_id', jQuery('#country_id').val() );
postparemeters = {country_id:datas.country_id};
this.$http.post(baseurl+'/api/v1/site/getMountain',postparemeters,function(response)
{
if(response.result)
this.$set('mountainlist',response.result);
else
this.$set('mountainlist','');
});
},
});
<select
class="breadcrumb_mountain_property"
id="country_id"
v-model="formVariables.country_id"
v-on="change:getMountain(formVariables.country_id);">
<option
v-repeat = "country: countrylist"
value="#{{country.id}}" >
#{{country.name}}
</option>
</select>
With vue 2, the provided answer won't work that well. I had the same problem and the vue documentation isn't that clear concerning <select>. The only way I found for <select> tags to work properly, was this (when talking of the question):
<select v-model="formVariables.country_id">
<option v-for = "country in countrylist" :value="country.id" >{{country.name}}</option>
</select>
I assume, that the #-sign in #{{...}} was due to blade, it should not be necessary when not using blade.
In VueJS 2 you can bind selected to the default value you want. For example:
<select
class="breadcrumb_mountain_property"
id="country_id"
v-model="formVariables.country_id"
v-on:change="getMountain(formVariables.country_id);">
<option
v-for = "country in countrylist"
:selected="country.id == 1"
:value="country.id" >
{{country.name}}
</option>
</select>
So, during the iteration of the countryList, the country with the id 1 will be selected because country.id == 1 will be true which means selected="true".
UPDATED:
As Mikee suggested, instead of v-on="change:getMountain(formVariables.country_id);" there is a new way to for binding events. There is also a short form #change="getMountain(formVariables.country_id);"
You should use the 'options' attribute in place of trying to v-repeat <option></option>:
VM
data: {
countryList: [
{ text:'United States',value:'US' },
{ text:'Canada',value:'CA' }
]
},
watch: {
'formVariables.country_id': function() {
// do any number of things on 'change'
}
}
HTML
<select
class="breadcrumb_mountain_property"
id="country_id"
v-model="formVariables.country_id"
options="countryList">
</select>
You can use select in this way. Remember to use array in v-for.
<select v-model="album.primary_artist">
<option v-for="i in artistList" :key="i.id" :value="i.name">
{{ i.name }}
</option>
</select>
You can use this way.
<select v-model="userData.categoryId" class="input mb-3">
<option disabled value="null">Kategori</option>
<option
v-for="category in categoryList"
:key="category.id"
:value="category.id"
>
{{ category.name }}
</option>
</select>
export default {
data() {
return {
categoryList: [],
userData: {
title: null,
categoryId: null,
},
};
},
The important thing here is what the categoryId value is, the default option value should be that.
categoryId: null,
<option disabled value="null">Kategori</option>
Here we use categoryId as value in v-model and initialize it with null. Value must be null in default option.
<select v-model="userData.categoryId" class="input mb-3">

Aurelia ValueConverter fromView confusion with multi-select

I'm trying to use and understand the Aurelia ValueConverter in the context of a multi-select form. What I thought would be straight forward, has turned out to be a challenge for me.
I have a form to create a new deal which has multiple categories assigned to it via a multi-select input field. I've bound the output from the form into new_deal.categorizations (in the database deals have categories through categorizations).
Right now on create, through a 'brute force' method, I'm converting each category ID into a {category_id: id} object before posting to the API.
Example just logging the POST output:
create(){
var categorizations = this.new_deal.categorizations;
this.new_deal.categorizations = categorizations.map(function (e) {
return {category_id: e}
});
logger.debug ('POST: ', JSON.stringify(this.new_deal));
}
Example output:
POST: {"name":"new deal","categorizations":[{"category_id":"1"},{"category_id":"2"}]}
But I think this would better be accomplished through a ValueConverter.
Plunker is here with the full code but it's basically:
app.js:
export class App {
constructor(){
this.categories = [{id: 1, name: 'test1'}, {id: 2, name: 'test2'}];
this.new_deal = {
name: 'new deal',
categorizations: null,
};
}
create(){
var categorizations = this.new_deal.categorizations;
this.new_deal.categorizations = categorizations.map(function (e) {return {category_id: e}});
logger.debug ('POST: ', JSON.stringify(this.new_deal));
}
create2(){
logger.debug ('POST: ', JSON.stringify(this.new_deal));
}
}
export class CategoryToIDValueConverter {
fromView(id) {
return id ? id: null;
}
}
And app.html:
<template>
<h1>Testing ValueConverter</h1>
<h3 >New Brute Force Deal</h3>
<form role="form">
<label>Name</label>
<input type="text" placeholder="Ex. Buy One Get One Free" value.bind="new_deal.name">
<label>Categories</label>
<select value.bind="new_deal.categorizations" multiple size="2">
<option repeat.for="category of categories" value.bind="category.id">${category.name}</option>
</select>
</form>
<button type="submit" click.delegate="create()">Save</button>
<h3>New ValueConverter Deal</h3>
<form role="form">
<label>Name</label>
<input type="text" placeholder="Ex. Buy One Get One Free" value.bind="new_deal.name">
<label>Categories</label>
<select class="form-control" value.bind="new_deal.categorizations | categoryToID" multiple size="2">
<option repeat.for="category of categories" value.bind="category.id">${category.name}</option>
</select>
</form>
<button class="btn btn-success" type="submit" click.delegate="create2()">Save</button>
</template>
With this I get an output of
POST: {"name":"new deal","categorizations":["1","2"]}
In fromView in app.js, I would think I could change:
return id ? id: null;
To return an object instead of an individual value:
return id ? {category_id: id} : null
But that results in this error:
Uncaught Error: Only null or Array instances can be bound to a multi-select.
Upon further inspection, it looks like id is coming into fromView as an array...
So I modified fromView to this:
fromView(id) {
if(id){
var categorizations = [];
id.forEach(function(cat_id){
categorizations.push({category_id: cat_id})
});
logger.debug(categorizations);
logger.debug(Object.prototype.toString.call(categorizations));
return categorizations;
} else { return null; }
}
}
Trying to expect an array, and then build an array of categorization objects to return, but as you can see in this Plunker, it loses the select as you click (though the debug logs show the objects being created).
You have an array of category objects, each having a name (string) and id (number). These will be used to populate a select element that allows multiple selection:
export class App {
categories = [
{ id: 1, name: 'test1'},
{ id: 2, name: 'test2'}
];
}
<select multiple size="2">
<option repeat.for="category of categories">${category.name}</option>
</select>
The deal object is comprised of a name (string) and categorizations. Categorization objects look like this: { category_id: 1 }
export class App {
categories = [
{ id: 1, name: 'test1'},
{ id: 2, name: 'test2'}];
deal = {
name: 'new deal',
categorizations: [],
}
}
We want to bind the select element's value to the deal object's categorizations which is an array of objects. This means each of the select element's options need to have a object "value". An HTMLOptionElement's value attribute only accepts strings. Anything we assign to it will be coerced to a string. We can store the categorization object in a special model attribute which can handle any type. More info on this can be found in the aurelia docs.
<select multiple size="2">
<option repeat.for="category of categories" model.bind="{ category_id: category.id }">${category.name}</option>
</select>
Finally we need to bind the select element's value to the deal object's categorizations:
<select value.bind="deal.categorizations" multiple size="2">
<option repeat.for="category of categories" model.bind="{ category_id: category.id }">${category.name}</option>
</select>
All together, the view and view-model look like this:
export class App {
categories = [
{ id: 1, name: 'test1'},
{ id: 2, name: 'test2'}];
deal = {
name: 'new deal',
categorizations: [],
}
createDeal() {
alert(JSON.stringify(this.deal, null, 2));
}
}
<template>
<form submit.delegate="createDeal()">
<label>Name</label>
<input type="text" placeholder="Ex. Buy One Get One Free" value.bind="deal.name">
<label>Categories</label>
<select value.bind="deal.categorizations" multiple size="2">
<option repeat.for="category of categories" model.bind="{ category_id: category.id }">${category.name}</option>
</select>
<button type="submit">Save</button>
</form>
</template>
Here's a working plunker: http://plnkr.co/edit/KO3iFBostdThrHUA0QHY?p=preview
Figured it out with some help from whayes on the Aurelia Gitter channel. So I was on the right track with expecting an array in the fromView method but I also needed a toView method in the ValueConverter.
export class CategoryToIDValueConverter {
toView(cats){
if (cats){
var ids = [];
cats.forEach(function(categorization){
ids.push(categorization.category_id);
});
return ids;
} else { return null; }
}
fromView(id) {
if(id){
var categorizations = [];
id.forEach(function(cat_id){
categorizations.push({category_id: cat_id})
});
return categorizations;
} else { return null; }
}
}
I had tried that too, but I initially assumed I needed to add the converter to the select line of the form and the option line, like so:
<select class="form-control" value.bind="new_deal.categorizations | categoryToID" multiple size="2">
<option repeat.for="category of categories" value.bind="category.id">${category.name}</option>
</select>
But that's actually incorrect. I only needed to apply the categoryToID ValueConverter to the select line and it all worked as expected.
Working Plunker showing how the brute force method doesn't change the model until you click save, and the ValueConverter changes it any time you change the selection.
Final app.js
import {LogManager} from 'aurelia-framework';
let logger = LogManager.getLogger('testItems');
export class App {
constructor(){
this.categories = [{id: 1, name: 'test1'}, {id: 2, name: 'test2'}];
this.new_deal = {
name: 'new deal',
categorizations: [],
};
setInterval(() => this.debug = JSON.stringify(this.new_deal, null, 2), 100);
}
create(){
var categorizations = this.new_deal.categorizations;
this.new_deal.categorizations = categorizations.map(function (e) {return {category_id: e}});
alert(JSON.stringify(this.new_deal, null, 2));
}
create2(){
alert(JSON.stringify(this.new_deal, null, 2));
}
}
export class CategoryToIDValueConverter {
toView(cats){
if (cats){
var ids = [];
cats.forEach(function(categorization){
ids.push(categorization.category_id);
});
return ids;
} else { return null; }
}
fromView(id) {
if(id){
var categorizations = [];
id.forEach(function(cat_id){
categorizations.push({category_id: cat_id})
});
return categorizations;
} else { return null; }
}
}
Final app.html
<template>
<h1>Testing ValueConverter</h1>
<h3 >New Brute Force Deal</h3>
<form role="form">
<label>Name</label>
<input type="text" placeholder="Ex. Buy One Get One Free" value.bind="new_deal.name">
<label>Categories</label>
<select value.bind="new_deal.categorizations" multiple size="2">
<option repeat.for="category of categories" value.bind="category.id">${category.name}</option>
</select>
</form>
<button type="submit" click.delegate="create()">Save</button>
<h3>New ValueConverter Deal</h3>
<form role="form">
<label>Name</label>
<input type="text" placeholder="Ex. Buy One Get One Free" value.bind="new_deal.name">
<label>Categories</label>
<select class="form-control" value.bind="new_deal.categorizations | categoryToID" multiple size="2">
<option repeat.for="category of categories" value.bind="category.id">${category.name}</option>
</select>
</form>
<button type="submit" click.delegate="create2()">Save</button>
<!-- debug -->
<pre><code>${debug}</code></pre>
</template>

Categories