i'm trying to get the selected option of a user task.
myresult
what my expected result is like this expected
Here is my Html code
<div class="form-group has-float-label">
<input v-model="form.name" type="text" name="name" placeholder="Name" class="form-control" :class="{ 'is-invalid': form.errors.has('name') }">
<has-error :form="form" field="name"></has-error>
</div>
<div class="form-group">
<select name="tasks" v-model="form.tasks" id="tasks" class="form-control" :class="{ 'is-invalid': form.errors.has('tasks') }">
<option disabled value="">Please select one</option>
<option v-for="t in alltask" :key="t"
v-bind:value="t" >{{t.name}}
</option>
</select>
<br />
{{form.tasks}}
</div>
Below is my JS code
<script>
export default {
data() {
return {
editmode: false,
users : {},
alltask : {},
form : new Form({
id: '',
name: '',
tasks: {},
})
}
},
methods: {
loadUsers(){
axios.get("/api/v1/users").then(({ data }) => (
this.alltask = data.alltask,
this.users = data.users
));
},
editModal(user){
this.editmode = true;
this.form.reset();
$('#users').modal('show');
this.form.fill(user);
}
},
created() {
this.loadUsers();
}
}
</script>
this is my json response
{
"users": [
{
"id": 1,
"name": "zxc",
"username": "zxc",
"tasks": [
{
"id": 1,
"name": "cooking"
}
]
},
{
"id": 2,
"name": "foo",
"username": "foo",
"tasks": [
{
"id": 2,
"name": "cleaning"
}
]
}
],
"alltask": [
{
"id": 1,
"name": "cooking"
},
{
"id": 2,
"name": "cleaning"
}
]
}
the value of v-model is the same with option value but i don't get it to get pre selected upon clicking update button, but if i change the option the v-model code that i put below the v-model itself is getting changed following the option list and i can update it to the db
The Problem is that you bind the whole object as value. Even though the object you receive from your call and the object you used to bind the value property to have the same "content" (props & values) they are not the same. So it will not be preselected.
What you actually should do is only bind the id of the task and if you want to display the result find the object that has the id from your alltask list
https://jsfiddle.net/eywraw8t/382079/
<select v-model="form.task">
<option>Please Select</option>
<option :value="t.id" v-for="(t, i) in alltask" :key="i">{{ t.name }}</option>
</select>
<p>
{{ selectedTask }}
</p>
As you only select one task I was wondering why you have "form.tasks" - for my example I changed it to singular.
The computed prop selectedTask could look like this
computed: {
selectedTask() {
return this.alltask.find(task => {
return task.id === this.form.task
})
}
}
Related
I'd like to have two select boxes for users to mention their location data.
When user chooses the province Bar from the first select box, the second selct box should be populated with the cities of the province:
Here is the json data:
Provinces: [
{
"Province": "Foo",
"Cities": [
{
"name": "Fooland"
},
{
"name": "Fooville"
}
} ,
{"Province": "Bar",
"Cities": [
{
"name": "Barland"
},
{
"name": "Barville"
},
{
"name": "Barak"
}
}
]
The province select box works fine:
<select v-model="province">
<option v-for="(p, index) in provinces" :key="index" >{{ p.Province }}</option>
selected: {{province}},
</select>
But I can not get the cities of Bar in the second select box:
<select v-model="city">
<option v-for="(c, index) in provinces.province.Cities" :key="index">{{ c.name }}</option>
</select>
Appreciate your hints on how to fix this?
TLDR: Change the first <select>'s value to be the selected province object (which contains Cities), and use that value to populate the second <select>'s options.
The value of <select> is the value of the selected <option>. if you don't explicitly specify a value for an <option>, the default value is the <option>s inner text (standard behavior). So, you can assign a value that is different from the <option> label, and the value can be an object:
<option :value="myOptionValue">My Option Label</option>
Thus, you can assign the underlying province object model (i.e., p in this case) to the <option>s in the provinces <select>:
<option :value="p" v-for="(p, index) in provinces">
Notice the :value="p", where p is the province object, containing Cities.
After selecting the province, province can be used in the cities <select> to populate its <options> with city names:
<select v-model="city">
<option v-for="(c, index) in province.Cities" :key="index">{{ c.name }}</option>
</select>
const Provinces = [
{
"Province": "Foo",
"Cities": [
{ "name": "Fooland" },
{ "name": "Fooville" }
]
},
{
"Province": "Bar",
"Cities": [
{ "name": "Barland" },
{ "name": "Barville" },
{ "name": "Barak" }
]
}
];
new Vue({
el: '#app',
data() {
return {
province: '',
city: '',
provinces: Provinces
}
},
watch: {
province(newValue) {
// reset city when province changes
this.city = '';
}
}
})
<script src="https://unpkg.com/vue#2.5.17"></script>
<div id="app">
<select v-model="province">
<option value="" disabled>Select province</option>
<option v-for="(p, index) in provinces" :value="p" :key="index">{{ p.Province }}</option>
</select>
<select v-model="city" :disabled="!province">
<option value="" disabled>Select city</option>
<option v-for="(c, index) in province.Cities" :key="index">{{ c.name }}</option>
</select>
</div>
I have the following select option :
<select ng-model="class_name" name="class_name" class="form-control">
<option ng-repeat="t in MemberClass" value="{{t}}">{{t.class_name}}</option>
</select>
I want to set default option MemberClass[0] to select option. I tried the following code but not working.
The JSON data is coming from Webservice...
//To fetch Member Class
$http.get('http://192.168.1.6:8080/apartment//member/class/list').then(function(response) {
$scope.MemberClass = response.data.list;
$scope.class_name = $scope.MemberClass[0]; // Not working
});
Member class JSON data is :
[
{
"class_id": 1,
"class_name": "Owner",
"class_details": "DCE"
},
{
"class_id": 7,
"class_name": "Staff "
},
{
"class_id": 10
"class_name": "Vendor"
}
]
Plunker sample : https://plnkr.co/edit/vVcrmOREkcVBBM2Ynhgv?p=preview
(Am getting error if I not select any option...)
You can utilize ng-options for this. It is the preferred way most of the times. Like this:
<select ng-model="class_name" ng-options="t as t.class_name for t in MemberClass">
</select>
Now, since you have $scope.class_name assigned as default value, it will be selected already.
working example
Use ng-init. Try like below.
<!DOCTYPE html>
<html ng-app="myApp" ng-controller="Ctrl">
<body>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<div class="form-group">
<label class="control-label col-md-3">Member Class </label>
<div class="col-md-4">
<select ng-model="class_name"
ng-init=" class_name = MemberClass[0]" name="class_name" ng-options="t as t.sub_class_name for t in MemberClass">
</select>
<p>Selected Value: {{class_name}} <p>
</div>
</div>
<button type="submit" ng-click="alertdata()">Save</button>
<script>
angular.module('myApp', [])
.controller('Ctrl', function($scope) {
var MemberClass;
$scope.MemberClass = [{
"sub_class_id": 1,
"sub_class_name": "Primary"
},
{
"sub_class_id": 2,
"sub_class_name": "Secondary "
},
{
"sub_class_id": 3,
"sub_class_name": "Dependent "
},
{
"sub_class_id": 4,
"sub_class_name": "Sub Member"
},
{
"sub_class_id": 5,
"sub_class_name": "None"
}
]
// $scope.class_name = $scope.MemberClass[0];
$scope.alertdata = function() {
$scope.class_name = "{}";
var parameter;
parameter = {
"member": {
"first_name": "first_name",
"role": [{
"role_id": 4
}],
"associated": "associated",
"class0": [JSON.parse($scope.class_name)],
"contect": [{
"intercom": "intercom"
}],
"individualdetails": [{
"gender": "gender"
}]
},
"address": [{
"street_address_1": "street_address_1"
}]
}
console.log(JSON.stringify(parameter));
};
});
</script>
</body>
</html>
You should definitly use ng-options for this
<select ng-model="class_name" ng-options="t as t.class_name for t in MemberClass">
</select>
To set a default, either set the $scope.class_name to a value of the MemberClass array or you can add an empty option tag as below which will be selected when the $scope.class_name is null
<select ng-model="class_name" ng-options="t as t.class_name for t in MemberClass">
<option value="">Select value</option>
</select>
I render a select multiple in Ractive with a computed list of all options possible, which works great. But I could not find a proper way of preselecting values.
So far I have something like:
data = [{
type: "Person",
Name: "John",
worksFor: [
"1",
"2"
]},{
type: "department",
id: "1",
Name: "Sales"
},{
type: "department",
id: "2",
Name: "Marketing"
},{
type: "department",
id: "3",
Name: "Accounting"
}]
new Ractive({
el: '#list',
template: DataTpl,
data: {myData: data},
computed: {
DepartmentList () {
//some code
return list_of_all_Departments;
},
PersonsList () {
//some Code
return list_of_persons
});
So in my Template I tried
{{#PersonsList}}
<select multiple>
{{#DepartmentList}}
<option value="{{id}}"
{{#if _.includes(PersonsList.worksFor, id)}} selected{{/if}}>{{Name}}
</option>
{{/DepartmentList}}
</select>
{{/PersonsList}}
But this just gave me a failed to compute. Does anyone know how to get those preselects?
This is one of the things where Ractive deviates from standards. You need to put a value attribute on <select>. The selected <option>'s value becomes <select>'s value. The kind of data you'll get from <select> depends if it's multiple or not. If it's a single-select, you get a single value. If it's multiple-select, you'll get an array.
Setting a pre-selected value is simply the other way around. Assign a value from your data to <select>'s value and, assuming those values exist on the <option>s, they'll be selected. No template mangling required.
Ractive.DEBUG = false;
var data = [{
type: "Person",
Name: "John",
worksFor: [
"1",
"2"
]
}, {
type: "department",
id: "1",
Name: "Sales"
}, {
type: "department",
id: "2",
Name: "Marketing"
}, {
type: "department",
id: "3",
Name: "Accounting"
}];
new Ractive({
el: '#list',
template: '#template',
data: {
selectedDepartments: [],
myData: data
},
computed: {
DepartmentList() {
return this.get('myData').filter(v => v.type === 'department');
},
PersonsList() {
return this.get('myData').filter(v => v.type === 'Person');
}
}
});
<script src="https://unpkg.com/ractive#0.8.11/ractive.min.js"></script>
<div id="list"></div>
<script type="template/ractive" id="template">
{{#PersonsList}}
{{ Name }}
<select multiple value="{{ worksFor }}">
{{#DepartmentList}}
<option value="{{id}}">{{Name}}</option>
{{/DepartmentList}}
</select>
{{/PersonsList}}
</script>
you must give the select a value and set the value to whatever is the default value
I'd like to create a nested ng-repeat that allows me to include all questions in all chapters of a survey JSON in a dropdown <select> menu. What's the "right way" to do this? I could see creating an array just for this particular use case, but would rather not do that.
<select class="form-control" ng-model="chapter.jumpId">
<span ng-repeat="chap in survey.chapters">
<option ng-repeat="question in chap.questions" value="question.verbose">
{{ question.id }}
</option>
</span>
</select>
Html:
<select ng-repeat="chap in survey.chapters">
<option ng-repeat="question in chap.questions" value="question.verbose">
{{ question.id }}
</option>
</select>
-----
<select>
<option ng-repeat="sOption in sOptions" value="sOption.verbose">
{{ sOption.id }}
</option>
</select>
Js:
$scope.survey = {
"chapters" : [
{
"questions" : [
{
"verbose" : "que1_verbose1",
"id": "que1_1"
},
{
"verbose" : "que1_verbose2",
"id": "que1_2"
}
]
},
{
"questions" : [
{
"verbose" : "que2_verbose1",
"id": "que2_1"
},
{
"verbose" : "que2_verbose2",
"id": "que2_2"
}
]
}
]
};
$scope.sOptions = [];
angular.forEach($scope.survey.chapters, function(chapter) {
angular.forEach(chapter.questions, function(question) {
$scope.sOptions.push(question);
});
});
http://jsfiddle.net/9bc06fdv/27/
So the overview of the problem; I am retrieving data from an api and creating a CRUD page for it. The data has a set of labels that the user can select.
Below is a code sample representing my problem. The labels selected by the user are represented by the user.labels relationship and the total available labels that can be selected are represented by user.parent.grandparent.labels.
I'm able to sync the selection. What I can't seem to figure out is how to get rid of options that have already been selected from the list of options on any other subsequent select field.
angular.module('app', [])
.controller('select', ['$scope', '$filter', '$location',
function($scope, $filter, $location) {
$scope.user = {
"parent": {
"grandparent": {
"labels": [{
"id": 28,
"name": "Label 1",
}, {
"id": 17,
"name": "Label 2",
}, {
"id": 39,
"name": "Label 3",
}, {
"id": 77,
"name": "Label 4"
}, {
"id": 100,
"name": "Label 5"
}]
}
},
"labels": [{
"id": 28,
"name": "Label 1",
"meta": {
"score": 3
}
}, {
"id": 17,
"name": "Label 2",
"meta": {
"score": 5
}
}]
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="select">
<div ng-repeat="label in user.labels track by $index">
<div class="form-field">
<span>Label</span>
<select ng-model="user.labels[$index]" ng-options="department.name for department
in user.parent.grandparent.labels track by department.id">
</select>
</div>
<div>
<span>Score</span>
<select ng-model="label.meta.score">
<option value="1">1 (lowest)</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5 (highest)</option>
</select>
</div>
</div>
<button ng-click="user.labels.push({})">Add Label</button>
</div>
You can use a filter function inside the ng-repeat to achieve this, here is a sample Codepen showing you how:
http://codepen.io/anon/pen/ZYveOo
You need to pass the filter in the repeat definition:
<select ng-model="user.labels[$index]" ng-options="department.name for department in user.parent.grandparent.labels | filter:removeSelected track by department.id ">
Which refers to this function on scope:
$scope.removeSelected = function(val){
return !_.find($scope.user.labels, function(label) {
return label.id === val.id;
});
};
Even then though I think you are missing one use case which is that you want to be able to have the currently selected label included in the options, by removing all selected options you are removing that ability.
Updated:
Ok then, so after giving this some thought I have come up with the following filter which could be optimised but does seem to work as expected:
.filter('duplicatesFilter', function() {
return function(items, index, selected) {
var res = [selected[index]];
_.forEach(items, function(item){
if(!_.find(selected, function(label) {
return label.id === item.id;
})){
res.push(item);
}
});
return res;
};
})
Use it like so:
<select ng-model="user.labels[$index]" ng-options="department.name for department in user.parent.grandparent.labels | duplicatesFilter:$index:user.labels track by department.id "></select>
This is something I have hit a few times and each time I've worked around it. I'll take a look later if I can find a custom filter that better solves the problem and if I can't I'll tidy up this code and release one; however this should be good to go for your use-case.
Working code-pen:
http://codepen.io/anon/pen/ZYveOo