I have a json data that i've been loading into the <select>
This is a sample json data that I have:
let plans = [{id: 20, name: "test", default: 0},
{id: 19, name: "haha", default: 0},
{id: 18, name: "okok", default: 1}];
This is my select html/vue.
<select id="plans" class="form-control" v-model="company.plan_id">
<option v-for="plan in plans" :value="plan.id" :selected="plan.default">{{plan.name}}</option>
</select>
It seems it doesn't select the "okok" value even if the default is 1.
Those plans data are coming from my database which is loaded using ajax.
I'm new to VueJS, any help is greatly appreciated!
Thanks.
selected attribute no longer makes sense when you using v-model.
You can't use selected attribute if you are using v-model on the <select>, Set the v-model value to the default value instead:
<template>
<div id="app">
<select id="plans" class="form-control" v-model="company.plan_id">
<option v-for="plan in plans" :value="plan.id" :key="plan.id" :selected="plan.default">{{plan.name}}</option>
</select>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
company: {
plan_id: 18
},
plans: [
{ id: 20, name: "test" },
{ id: 19, name: "haha" },
{ id: 18, name: "okok" }
]
};
}
};
</script>
Demo here: https://codesandbox.io/s/beautiful-sound-gxmzu?file=/src/App.vue
Related
When I try to show default selected value it doesn't show up i.e the option does not get selected in dropdown. The default value is coming from database and I'm setting that value in the model variable pageData.fields[content.id].keyFollowing is the sample JSON that I'm using to populate the dropdown:
$scope.dropdownFields = [{
groupName: 'PAGE',
isOptDisabled: false,
items: [{
name: 'PageName1',
type: 'page'
},
{
name: 'PageName2',
type: 'page'
},
{
name: 'PageName3',
type: 'page'
},
{
name: 'PageName4',
type: 'page'
}
]
},
{
groupName: 'COLOR',
isOptDisabled: false,
items: [{
name: 'COLOR1',
type: 'component'
},
{
name: 'COLOR2',
type: 'component'
},
{
name: 'COLOR3',
type: 'component'
}
]
},
{
groupName: 'OTHERS',
items: [{
name: 'Bold',
type: 'others',
isOptDisabled: false,
itemList: [{
name: 'Yes',
value: true
},
{
name: 'No',
value: false
}
]
},
{
name: 'Italic',
type: 'others',
isOptDisabled: false,
itemList: [{
name: 'Yes',
value: true
},
{
name: 'No',
value: false
}
]
}
]
}
];
<select id="{{content.id}}_filter" ng-model="pageData.fields[content.id].key" class="form-control" ng-change="onChangeFilter(pageData.fields[content.id].key, content.id)">
<option value="">[Select an option]</option>
<optgroup ng-repeat="header in dropdownFields" label="{{ header.groupName }}">
<option ng-repeat="item in header.items" value="{{ item.name }}" ng-disabled="isDisabled(header.groupName, item.name)">{{ item.name}}
</option>
</optgroup>
</select>
Is there any way to do this as I've researched a lot on this but the solutions were with ng-options and I cannot use ng-options for creating the dropdown due the disability functionality. The AngularJS version that I'm using is 1.2Any suggestion into the direction will be appreciated. Thanks.
EDIT: The code is successfully populating the dropdown and I'm able to get the value of selected option as well. But I'm not able to set an option by default into the dropdown. For eg. PageName3 is already selected in the dropdown.
EDIT2: So far now I'm able to show default value selected in this combobox on button click(here's the plnk) but I'm not able to set this value when I redirect from another page to this page.
So it goes like this, on this page(say PAGE1) I fill in these values there are multiple such dropdowns and textboxes in front of them for values, then I pass these values to the next page(say PAGE2); on PAGE2 I have a back button on the click of this button I return to PAGE1 with the same values passed before and I've to set all these values back as it were before. This is where I'm stuck! Not able to set selected values in dropdown while setting textboxes is done.
You can add default option into dropdown like so:
<input type="checkbox" ng-model="selected"></label><br/>
<select ng-model="item.name" ng-click="onChangeFilter(item.name)" class="form-control" >
<optgroup ng-repeat="header in dropdownFields" label="{{ header.groupName }}">
<option ng-selected="selected">Greetings!</option>
<option ng-repeat="item in header.items">{{item.name}}</option>
</optgroup>
</select>
plunker: http://plnkr.co/edit/vszVo3BHEA3T4yxGSUkA?p=preview
I have a group of selects but want them all to work differently with v-model without creating separate data properties for them all.
In the example, select 1 and select 2 are one group and select 3 and select 4 are another.
When one select select 1, the expected behavior should be that, it does not affect select 2, etc.
My guess is may be a computed property for this? but can't get my head around the proper implementation
Js fiddle: https://jsfiddle.net/uxn501h2/8/
Code snippet:
new Vue({
el: '#app',
template: `
<div>
Select 1: <select v-model="selectedPerson">
<option v-for="person in people" :value="person.key">{{person.name}}</option>
</select>
Select 2: <select v-model="selectedPerson">
<option v-for="person in people" :value="person.key">{{person.name}}</option>
</select>
<h4>Selected 1 person key : {{selectedPerson}}</h4>
<h4>Selected 2 person key: {{selectedPerson}}</h4>
<br/>
Select 3: <select v-model="selectedPersonTwo">
<option v-for="person in people" :value="person.key">{{person.name}}</option>
</select>
Select 4: <select v-model="selectedPersonTwo">
<option v-for="person in people" :value="person.key">{{person.name}}</option>
</select>
<h4>Selected 3 person Two key: {{selectedPersonTwo}}</h4>
<h4>Selected 4 person Two key: {{selectedPersonTwo}}</h4>
</div>
`,
data: {
people: [{
key: 1,
name: "Carl"
},
{
key: 2,
name: "Carol"
},
{
key: 3,
name: "Clara"
},
{
key: 4,
name: "John"
},
{
key: 5,
name: "Jacob"
},
{
key: 6,
name: "Mark"
},
{
key: 7,
name: "Steve"
}
],
selectedPerson: "",
selectedPersonTwo: ""
}
});
.required-field > label::after {
content: '*';
color: red;
margin-left: 0.25rem;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.js"></script>
<body>
<div id="app"></div>
</body>
It looks to me that you'd like to use two-way binding, but with more control between them in the middle. My suggestion would be:
Do not use <select v-model="selectedPerson">
Instead split them to <select :value="selectedPersonValue" #input="selectedPersonOutput> (which is basically the same thing, but you can specify different input and outputs), where selectedPersonValue can be a computed property or a regular property in data(), and selectedPersonOutput should be a method that will be called when select value changes.
This way you can directly decide what happens on each step.
PS: If you want to influence your property selectedPersonValue from a method, you might consider changing it to data() property and add a watch to it. See what works best for you.
While I am trying to create a form I encountered this problem which I don't have any solution.
There is a Vuex data on Vehicles Make and Model of vehicle, now once the make is selected, I want the other form to loop through the selected Make and find other models... something like that.
Here is what I did so far:
cars.js - (vuex module)
const state = {
make: [
{
name: 'Audi',
carid: '1',
models: [
{
modelid: '1.1',
name: 'A7',
},
{
modelid: '1.2',
name: 'A8',
},
],
},
{
name: 'BMW',
carid: '2',
models: [
{
modelid: '2.1',
name: '5 Series',
},
{
modelid: '2.2',
name: '7 Series',
},
],
},
],
}
Cars.vue
<template>
<div class="labelos">
<div class="label-name">
<h4>Car make:</h4>
</div>
<div class="label-body">
<label for="car-make">
<select v-model="selectedType" name="carmake" required>
<option value=""></option>
<option v-for="(cars, index) in cars.make" :key="index" :value="cars.carid">{{ cars.name }}</option>
</select>
</label>
</div>
</div>
<div class="labelos">
<div class="label-name">
<h4>Car model:</h4>
</div>
<div class="label-body">
<label for="car-model">
<select>
<option value=""></option>
<option v-for="(model, index) in cars.make" :key="index" :value="cars.carid">{{ model.carid }}</option>
</select>
</label>
Model:
</div>
</div>
</template>
<script>
import { mapState } from 'vuex';
export default {
name: 'cars',
data() {
return {
selectedType: '',
selectedCity: '',
};
},
methods: {
},
components: {
Headers,
Footers,
},
computed: {
...mapState([
'cities', 'cars',
]),
},
};
</script>
So as you can see on first label I am looping through makes, and once a car make is selected that carid is saved on selectedType, now how is that possible to load second dropdown according to that selection, so if carid 1 is selected, the list will load car models available on given carid (in this example carid 1)
Looking forward to hear from someone, I am stuck here.. I don't know any solution how to do this... this is so far I have done
Cheers
You should create a computed property which returns model options based on the value of the selected make type. Then you can bind to that and it will automatically update whenever the selected make changes:
models() {
if (this.selectedType) {
return this.cars.make.find((car) => car.carid === this.selectedType).models;
}
}
Here's a working example:
const store = new Vuex.Store({
state: {
cars: {
make: [{
name: 'Audi',
carid: '1',
models: [
{ modelid: '1.1', name: 'A7' },
{ modelid: '1.2', name: 'A8' },
]
}, {
name: 'BMW',
carid: '2',
models: [
{ modelid: '2.1', name: '5 Series' },
{ modelid: '2.2', name: '7 Series' }
],
}]
}
}
})
new Vue({
el: '#app',
store,
data() {
return {
selectedType: '',
};
},
computed: {
...Vuex.mapState(['cars']),
models() {
if (this.selectedType) {
return this.cars.make.find((car) => car.carid === this.selectedType).models;
}
}
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.0.1/vuex.min.js"></script>
<div id="app">
<h4>Car make:</h4>
<select v-model="selectedType" name="carmake" required>
<option value=""></option>
<option v-for="(cars, index) in cars.make" :key="index" :value="cars.carid">{{ cars.name }}</option>
</select>
<h4>Car model:</h4>
<select>
<option value=""></option>
<option v-for="(model, index) in models" :key="index" :value="model.modelid">{{ model.name }}</option>
</select>
</div>
Working example with your data:
const state = {
make: [
{
name: 'Audi',
carid: '1',
models: [
{modelid: '1.1', name: 'A7'},
{modelid: '1.2', name: 'A8'}
]
}, {
name: 'BMW',
carid: '2',
models: [
{modelid: '2.1', name: '5 Series'},
{modelid: '2.2', name: '7 Series'}
]
}
]
}
new Vue({
el: '#app',
data: {
state: state,
selected: 0
},
computed: {
models () {
var maker = this.state.make.find(m => m.carid === this.selected)
return maker ? maker.models : []
}
}
})
<div id="app">
<select v-model="selected">
<option value="0" selected>Choose maker</option>
<option
v-for="maker in state.make"
:key="maker.carid"
:value="maker.carid"
>{{ maker.name }}</option>
</select>
<br>
<select>
<option value="0" selected>Select model</option>
<option
v-for="model in models"
:key="model.modelid"
:value="model.modelid"
>{{ model.name }}</option>
</select>
</div>
<script src="https://unpkg.com/vue#2.5.3/dist/vue.min.js"></script>
If you can, change 'modelid' to simple integers - 1, 2, etc., at least. And if you can and you know how to do it, change your data structure - divide makers and models to separate arrays/objects.
Here's a plugin for this specific task you're trying to accomplish: vue-dependon.
It hasn't been updated for 1-2years, but I think that you can check its source code and see how it works.
UPDATE:
All you need from the sourcecode is the loadOptions function and the code between L83 and L105.
You can adapt that code to your needs.
I have two arrays of objects, one array being a subset of the other:
$scope.taskGroups = [
{id: 1, name: 'group1', description: 'description1'},
{id: 2, name: 'group2', description: 'description2'},
{id: 3, name: 'group3', description: 'description3'}
];
$scope.selectedGroups = [
{id: 1, name: 'group1', description: 'description1'},
{id: 2, name: 'group3', description: 'description3'}
];
After unsuccessfully trying to get my head around using ng-option, I thought that I could perhaps create a function to determine if an option should be selected in the select list, based on what I picked up in the documentation:
ngSelected
- directive in module ng Sets the selected attribute on the element, if the expression inside ngSelected is truthy.
So, I came up with this function:
$scope.inSelectedGroups = function(taskGroup) {
angular.forEach($scope.selectedGroups, function(group) {
if (taskGroup.id == group.id) {
return true;
}
return false;
});
};
and tried to use it in this html:
<select multiple ng-model="selectedGroups" style="width: 100%" size="7">
<option ng-repeat="taskGroup in taskGroups" value="{{taskGroup.id}}" ng-selected="inSelectedGroups(taskGroup)">{{taskGroup.name}}</option>
</select>
but, no dice - the full list of taskGroups shows, but the selectedTaskGroups aren't, well, selected...
Am I barking up the wrong tree here?
the full list of taskGroups shows, but the selectedTaskGroups aren't,
well, selected.
I tried your solution which is using the ngSelected attribute but I was unsuccessful as well so I tried using the ngOptions instead and it works.
angular.module('app', []).controller('TestController', ['$scope',
function($scope) {
$scope.taskGroups = [{
id: 1,
name: 'group1',
description: 'description1'
}, {
id: 2,
name: 'group2',
description: 'description2'
}, {
id: 3,
name: 'group3',
description: 'description3'
}];
$scope.selectedGroups = [{
id: 1,
name: 'group1',
description: 'description1'
}, {
id: 2,
name: 'group3',
description: 'description3'
}];
}
])
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="TestController">
<select multiple="true" ng-model="selectedGroups" style="width: 100%" ng-options="taskGroup.id as taskGroup.description for taskGroup in taskGroups track by taskGroup.id" size="7">
</select>
</div>
See carefully, you are returning Boolean value from function defined in angular.forEach parameter and so nothing is returned from inSelectedGroups function
Try modifying your function to:
$scope.inSelectedGroups = function(taskGroup) {
var flag = false;
angular.forEach($scope.selectedGroups, function(group) {
if (taskGroup.id == group.id) {
flag = true;
return;
}
flag = false;
return;
});
return flag;
};
http://jsfiddle.net/WcJbu/
When I select a person, I want the favoriteThing selector to display their current selection.
<div ng-controller='MyController'>
<select ng-model='data.selectedPerson' ng-options='person.name for person in data.people'></select>
<span ...> likes </span>
<select ... ng-model='data.favoriteThing' ng-options='thing.name for thing in data.things'></select>
</div>
$scope.data.people = [{
name: 'Tom',
id: 1,
favorite_thing_id: 1
}, {
name: 'Jill',
id: 2,
favorite_thing_id: 3
}];
$scope.data.things = [{
name: 'Snails',
id: 1
}, {
name: 'Puppies',
id: 2
}, {
name: 'Flowers',
id: 3
}];
Do I need to set up a service and add watches, or is there a [good] way to use the favorite_thing_id directly in the select?
Change the second select to this:
<select ng-show='data.selectedPerson' ng-model='data.selectedPerson.favorite_thing_id'
ng-options='thing.id as thing.name for thing in data.things'></select>
Adding the thing.id as to the ng-options will allow you to select the data.things entries based on their id's instead of their references. Changing the ng-model to data.selectedPerson.favorite_thing_id will make angular automatically change to the correct option based on selectedPerson.favorite_thing_id.
jsfiddle: http://jsfiddle.net/bmleite/4Qf63/
http://jsfiddle.net/4Qf63/2/ does what I want - but it's pretty unsatisfying.
$scope.$watch(function() {
return $scope.data.selectedPerson;
}, function(newValue) {
if (newValue) {
$scope.data.thing = $filter('filter')($scope.data.things, {id: newValue.favorite_thing_id})[0];
}
})
I'd like to see all of that be possible from within the select statement.
Maybe I'll try to write a directive.
association = {key: matchValue}
So that I can do
<select ... ng-model='data.thing' ng-options='t.name for t in data.things' association='{id: "data.selectedPerson.favorite_thing_id"}'></select>