Assign option's description to a variable on select - angularjs

I am using ng-options to populate my select. I assign the value to be the id of the field however I need to assign the description of my option as well.
Not sure how to do that without iterating through my list separately afterwards to find the matching id.
So I am assigning the user's id to the vm.model.user but how can I possibly assign name to a different variable and still make this generic. The key part is this being generic as the description name might vary (sometimes it's description or userDescription etc. and I cannot control that).
$scope.users = [
{ id: 1, name: 'John' },
{ id: 2, name: 'Adam' },
{ id: 3, name: 'Chloe' },
{ id: 4, name: 'Chris' }
];
<select ng-model="vm.model.user" ng-options="user.id as user.name for user in users | orderBy: 'name'"></select>
I have tried doing this on ng-change but it seems it is not aware of user, only ng-options is.
ng-change="vm.model.userDescription = user.name"

One solution would be to set ng-model with the the selected user object, so vm.model.user would have both id and name:
<select ng-model="vm.model.user" ng-options="user as user.name for user in vm.users | orderBy: 'name'"></select>
Check demo: DEMO

I found this interesting answer
https://stackoverflow.com/a/28323031/9559251
Basically we could just do
ng-change="vm.model.userDescription = (users | filter: {id: vm.model.user})[0].name"

Related

how to make dropdown select a certain value from getting the id from the database?

The code below show a dropdown list from using ng-repeat. When I edit this entity, I have to make them show a certain value selected already than just showing a whole list. I know that I can put selected keyword when I want to select a certain value.
Then what if I used ng-repeat to populate a dropdown? How can I make a dropdown choose a certain value using the id?
<div ng-if="field.name=='ClienteleId'" class="input-group inputFill">
<select ng-disabled="defaultSaveButtons[$index]" class="form-control inputFill2"
ng-model="field.value" ng-options="clientele.id as clientele.name for clientele in dropdown.clienteleOptions | orderBy:'name' track by clientele.id"></select>
/div>
To set the value of a <select> in AngularJS, you need to change the variable that is set as its ng-model to one of the values in your options.
In your case, you have field.value as your ng-model, and your options use the name attribute as their label and the id attribute as their value. To have one of the items in dropdown.clienteleOptions selected by default, you need to set field.value to the id attribute of the corresponding entry in dropdown.clienteleOptions.
Imagine your options and fields look like this:
$scope.clienteleOptions = [
{id: 1, name: 'test 1'},
{id: 2, name: 'test 2'}
];
$scope.fields = [
{name: 'ClienteleId', value: null}
// ...
];
In your controller somewhere, you would have something like this to have test 2 selected:
$scope.fields[0].value = 2;
Or to make it more dynamic:
$scope.fields.forEach(function (field) {
if (field.name === 'ClienteleId') {
field.value = 2;
}
});

AngularJS: refresh ng-options when property source object changes

Full description:
I have list of options with multiple properties (not just key-value pair):
[
{
id: 1,
name: "111",
some: "qqq"
},
{
id: 2,
name: "222",
some: "www"
}
];
And select defined as:
<select name="mySelect" id="mySelect"
ng-options="option.name for option in opts track by option.id"
ng-model="mod1"></select>
Depending on app logic, extra property may change:
{
id: 2,
name: "222",
some: "www1"
}
But actual list in Select doesn't change!
However, if name changes, then entire optionList will be refreshed.
In short you can see demo on JSFiddle OR JSFiddle. I prepared 2 very similar examples:
When button is clicked only extra property updates
When button is clicked - both extra property and key receive new value
Does anybody know solution?
UPDATE
For now I'm solving that issue with update + delay + update solution:
this.click = function(){
$scope.opts = {};
$timeout(function() {
$scope.opts = { /* NEW OBJECT */};
}, 0);
}
OK, so I think I understand what you want, which is to be able to select an option whose nested values may have changed since the list was rendered in the DOM.
Based on that understanding, I believe that the plunker I have created illustrates a solution for you. If you select one of the options, and change the child value in the input field, two-way binding will update the model.
Basically, it is taking the users selection, and on select change, re-assigning the selected object to reference the original option in the options array. This will allow two-way binding to occur. If you view the code, you will see that the input fields are updating the option list itself ($scope.options), where-as the model that is being displayed is $scope.formData.model.
https://plnkr.co/edit/DLhI7t7XBw9EbIezBCjI?p=preview
HTML
<select
name="mySelect"
id="mySelect"
ng-model="formData.model"
ng-change="onChange(formData.model)"
ng-options="option.name for option in options track by option.id"></select>
SELECTED CHILD: {{formData.model.child.name}}
<hr>
<div ng-repeat="option in options">
Child Name for {{ option.name }}: <input ng-model="option.child.name">
</div>
JS
$scope.onChange = function(option) {
angular.forEach($scope.options,function(optionItem){
if (optionItem.id == option.id){
$scope.formData.model = optionItem;
}
})
}
$scope.options = [
{
id: 1,
name: "111",
child: {
id: 11,
name: "111-1"
}
},
{
id: 2,
name: "222",
child: {
id: 22,
name: "222-1"
}
}
];
$scope.formData = {
model: $scope.options[0]
};
Call $apply whenever you want to apply changes made.
$scope.$apply();
This will tell AngularJS to refresh.

AngularJS: Select with ng-options- how to pass value as integer?

I am having an issue with my select form. When I select any option, the value that is being passed is of a string type, instead of number type. Here is my object that I use for ng-repeat:
$scope.apples ={
0:'Apple0',
1:'Apple1',
2:'Apple2',
3:'Apple3'
};
And here is my select, which passes string, instead of number:
<select ng-model="test" ng-options="key as value for (key,value) in apples"></select>
Any ideas?
Every time you're iterating on object fields, IMO, there is a design problem. Use an array:
$scope.apples = [
{
id: 0,
name: 'Apple0'
},
{
id: 1,
name: 'Apple1'
},
...
];
and in the view:
ng-options="apple.id as apple.name for apple in apples"
Very simple approach is to actually cast string to number (note, + operator):
ng-options="+key as value for (key,value) in apples"
It's also possible to use array as data structure:
$scope.apples = [
'Apple0',
'Apple1',
'Apple2',
'Apple3'
];
and then
ng-options="apples.indexOf(apple) as apple for apple in apples"

ng-option dropdown list of objects not setting ng-option when selected = true

I have an Object Student {id,name, subject:{id,name}}
I want to prepopulate value of student when clicked on edit student. I want to show subjects in drop down list with selected value as student's assigned subject.
For example:
I have a student with
{id:1,
name:abc,
subject:{id:2,name:maths}}
And I have a subject list as
{id:1,name:english,
id:2,name:maths,
id:3,name:computers}
select.form-control(name="subject", id="subject", ng-required="true", ng-model="student.subject", ng-options="subject.name for subject in subjects")
option( value="", ng-selected="true") --choose subject--
I am using jade as the template and AngularJs (version 1.0.7)
The data structure doesn't make sense, you need a list of objects (JSON) like this
$scope.subjects = [{
id: 1,
name: 'english'
}, {
id: 2,
name: 'maths'
}, {
id: 3,
name: 'computers'
}]

How to sort object data source in ng-repeat in AngularJS?

Suppose I have the following users:
$scope.users = {
"2": {
email: 'john#gmail.com',
name: 'John'
},
"3": {
email: 'elisa#gmail.com',
name: 'Elisa'
}
}
I would like to create a <select> with the following options:
<option value="3">Elisa</option>
<option value="2">John</option>
In other words, users should be sorted by name.
I tried the following using the (key, value) in expression syntax, but it doesn't work:
<option ng-repeat="(user_id, user) in users | orderBy:'user.name'"
value="{{ user.id }}">
{{ user.name }}
</option>
Live example here.
What am I missing?
Please do not suggest solutions with ng-options as I use ui-select2 which is incompatible with ng-options.
While you would see this in the thread the author's answer references in a link, I thought it would be good to put up one of the mentioned workarounds up on SO:
It is true that this is technically not implemented, but there is an easy work around if you're willing to change your data model slightly: use a custom filter to generate an array of the object's properties (without replacement). If you add the key field to the objects ("id" in the above case), you should be able to get the behavior your looking for:
app.filter("toArray", function(){
return function(obj) {
var result = [];
angular.forEach(obj, function(val, key) {
result.push(val);
});
return result;
};
});
...
$scope.users = {
1: {name: "John", email: "john#gmail.com", id: 1},
2: {name: "Elisa", email: "elisa#gmail.com", id: 2}
};
Here's the ng-repeat directive that could be used:
<option value="{{user.id}}" ng-repeat="user in users | toArray | orderBy:'name'">{{user.name}}</option>
And here's the plunkr.
Notice that the orderBy filter takes name as its parameter and not user.name.
Unfortunately, adding the id property to your objects does create potential for mismatch with it's key in the containing object.
In the link you mentioned in your answer, there are also proposed solutions that create the id property in the user objects on the fly, but I feel like this approach is a little less messy (at the cost of introducing data replication).
OK, I found the answer:
It is not implemented yet :(
Adding to the accepted answer and seeing your data format, you should transform your data as
app.filter('myFilterUsers',function(){
return function(data)
{
var newRes = [];
angular.forEach(data,function(val,key){
val["id"] = key; //Add the ID in the JSON object as you need this as well.
newRes.push(val);
});
return newRes;
}
});

Resources