Programmatically selecting ng-options bound to object data source - angularjs

I have an ng-options select bound to an object. Setting the ng-model programmatically only works properly (updates the select) when setting it as a string. If I set the ng-model as an integer, it doesn't work. I really don't want to have to make this conversion. Is this the only way?
http://jsfiddle.net/HMjnV/1/
<div ng-controller="MyCtrl">
<select ng-options="id as name for (id, name) in items" ng-model="selected"></select>
<div>Selected ID: {{selected}} </div>
<button ng-click="setSelected(1)">Set Selected to ID 1 as Integer</button>
<button ng-click="setSelected('1')">Set Selected to ID 1 as String</button>
<div>Programmatically setting the ng-model as string sets the dropdown but not as integer.</div>
</div>
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.items = {1: 'a', 2: 'b', 3:'c'};
$scope.selected = null;
$scope.setSelected = function(id) {
$scope.selected = id;
}
}

EDITED
You might try using toString when you programmatically set the model value, if you're looking for a quick and dirty solution. See #ExpertSystems answer for detail on the core of the problem.
$scope.setSelected = function(id) {
$scope.selected = id.toString();
}

This is odd, but you can get the binding between ng-options and ng-model to work by forcing a cast to occur in the comprehension expression:
ng-options="id*1 as name for (id, name) in items"
Here is a fork of your fiddle demonstrating this trick: http://jsfiddle.net/wittwerj/HMjnV/9/
Having said that, I do prefer Marc's approach of converting toString in the controller.

Yes to pre-populate the value like you have done then definitely it should be a string. Since the value attribute in option tag takes only String. But yes in AngularJs you can give references like this given in the fiddle . And the workaround to your problem will be converting id to string.

JS Objects have property name-value pairs.
value can be of any type, but name is always a string.
Although you think you define it as a number, it is automatically converted to string.
There is no way you can change that (i.e. create an object with number property-names).

Related

AngularJS dropdown selected values need as JSON

I have multiple dropdowns in my application which are populating through a json (which is a map basically) given in controller.
For first dropdown if I select xyz value, then corresponding xyz1 values should come in dropdown and similarly for third dropdown. This all is happening fine currently. But now I want these user selected values to get in json form so that I can send back to backend for further processing. I am not getting selected values but the wrong second dropdown values if I print on console.
codepen and
working plunker
I understand that you need to get values from the dynamic input elements. For that, you need to set ng-model to the input elements, not to the div.
The below updated part would help.
<div ng-init="pageObjectName.pageObjParam={}" ng-repeat="(key , value) in pageObjectName.pageObjMethod">
<input ng-model='pageObjectName.pageObjParam[key]' value='' placeholder="{{key}} - {{value}}"></input>
</div>
Now you can get those values from $scope.pageObjectName.pageObjParam.
Updated Plunker
EDIT
I hope the above part helped to get value from dynamic input fields. Now I suggest you to update the code block like below to get the selected values from dropdown (ie, use one hidden input field for each select) and you will get what you want.
<select id="pageObj" ng-model="pageObjectName.pageObj" ng-options="key for (key,value) in pageData" ng-change="pageObjectName.pageObjParam.pageObj=pageObjectName.pageObj">
<option value=''>Select Page Object</option>
</select>
<input ng-model='pageObjectName.pageObjParam.pageObj' hidden/>
You can have a look at the same plunker now
Your codepen seems to be confusing and not working. As you already have the implemention for dropdown I will continue from here about how to get the data from the drop down and convert the data into a JSON.
After getting the data from the dropdown create a JSON object and store it.
I have written a small example to show how to store the data.
$scope.selectedState = function(item) {
var output = {};
output.name = item.name;
$scope.viewOutput = output;
};
Update:
I tried hard but could not get the values using angular way. If you are still looking for an answer then we can use basic javascript way. Refer plunker for the same.
$scope.submitMyForm = function() {
/* while compiling form , angular created this object*/
var pgObj = $scope.pageObj;
var pgClass = $scope.pageClass;
var pgMethod = $scope.pageObjMethod;
var pgObjvalue = document.getElementById('pageObj').value;
var pgClassvalue = document.getElementById('pageClass').value;
var pgMethodvalue = document.getElementById('pageMethod').value;
$scope.output = {'object' : pgObjvalue, 'class': pgClassvalue, 'method': pgMethodvalue};
console.log(data);
};
Working Plunker.
P.S: If you figured out the answer using angular way then do let me know after posting it in the answer section.

How to set the ng-options default using object?

If i set a value dropdown value as a object is not working as expected.
for Example :
HTML:
<select ng-model="selected" ng-options="lst as lst.name for lst in list"></select>
JS:
$scope.list=[{'name':'Person-1','age':23},
{'name':'Person-2','age':14},
{'name':'Person-3','age':32},
{'name':'Person-4','age':34},
{'name':'Person-5','age':67},
{'name':'Person-6','age':12}];
$scope.selected = {'name':'Person-3','age':32};
If i assign a value as $scope.selected = $scope.list[0] is working fine. But now how can i assign a object to select.
i have attached the plunker link : http://plnkr.co/edit/WJo0W688s5NDN7kZYOPR?p=preview
It's because the object which you are assigning is not there in $scope.list. However it looks same but it's a different object. $scope.list[0] is working because it points to the same object reference which $scope.list is having.
See updated plunker so that you can understand.
Updated
If you have objects then you need to iterate over the $scope.list by comparing properties and find index of appropriate object and use that index to assign selected object like.
$scope.selected = $scope.list[matchIndex]
$scope.selected = $scope.list[0];
This is how you set the default option

ng-model and ng-options not matching up?

I have a method in my resources object that comes in as:
resources.type
otherstuff: 'more strings'
type:'specifictype'
morestuff: 'morestuff'
The user can change this type with a dropdown / through another call that gets a list of all possible types which looks like resourceList.types which has a list of objects like this json
types:
[
{name:'resourcetype1'},
{name:'resourcetype2'},
etc...
],
my html looks like:
<select ng-model="resources.type" ng-options="name.name for name in resourceList.types">
</select>
The select/drop down box populates with my resourceList.type stuff but when the page loads the ng-model doesn't set to the already selected resource type. It actually selects a blank entry at the top of the drop down when you click. Is angular picky about this? How can I get the ng-model to behave the way I want it to?
I tried messing around with ng-options with the different ways of getting the repeat but I feel like this is more how angular connects the model. Does it just match the string to the ng-options list?
Here's the plnkr as you can see it's not defaulting to type1
http://plnkr.co/edit/NyWACtFQuyndR6CG8lpN?p=info
In Angular, the model is the single source of truth.
This means that if you want a value selected (and bound to your ngModel) you need to assign it to the model:
<select ng-model="resources.type"
ng-options="type.name as type.name for type in resourceList.types">
</select>
$scope.resources = {...};
$scope.resourceList = {
...
types: [
{name: 'resourcetype1'},
{name: 'resourcetype2'},
...
]
};
// Set the model to the desired value
$scope.resources.type = $scope.resourceList.types[0].name;
See, also, this short demo.
You don't have to set your model's value to the reference object in resourceList. In fact, the accepted answer works fine without this line:
$scope.resources.type = $scope.resourceList.types[0].name;
How is it working? Thanks to the "as" notation in the ngOptions. Without the "as", the match is made on the full type element, which is an object, so the match is made on the reference's object, not the name's value.
With the "as" the match is made on the element's property, name.
I've forked the plunker: http://plnkr.co/edit/kORfxGdsWBUlFWHXp6Ry?p=preview
in my case it didnt work since ngOptions was an array of integers and i was trying to set ngModal to string type (2the year 2014).
the solution is simple: parseInt function

Can't get Angular-xeditable Editable-Select to Select the current item when it is bound to a nested JSON object

I can't get the Angular-xeditable Editable-Select to Select the current item when it is bound to a nested JSON object. Data all saves fine, but it just doesn't show up the currently selected item in the Select box, which is driving me nuts, as I am sure I am missing something obvious. I have created a JSFiddle here:
http://jsfiddle.net/NfPcH/1031/
This is the code:
<span editable-select="data.organisation.OrganisationType"
e-ng-options="type.Name for type in data.types">
{{data.organisation.OrganisationType.Name}}
</span>
These are the 2 data objects:
$scope.data.organisation = {
"Id":1,
"Name":"My Organisation",
"OrganisationType":{"Id":2,"Name":"Internal"}
}
$scope.data.types = [
{"Id":1,"Name":"Client"},
{"Id":2,"Name":"Internal"},
{"Id":3,"Name":"Cold"}
]
It works fine when I bind it to the ID within the Nested Object, but then it only changes the Id in my nested object, and I then have to manually filter and change the Name part of the object, which works, but I am sure there must be a better way.
When the item is selected $data is loaded with the id of the item selected. You can use this to retrieve the value after the selection is made.
<span editable-select="data.organisation.OrganisationType"
e-ng-options="type.Name for type in data.types">
{{ findTypeName($data) || data.organisation.OrganisationType.Name}}
</span>
You can then define findTypeName in your controller
$scope.findTypeName = function(id) {
var found = $scope.data.types.filter(function(t){
return (t.Id === id);
});
return found.length ? found[0].Name : null;
};
The trick resides on using the object on the select's ng-options (e.g. 'obj as obj.title') and not a property of the object, so that when an item gets selected, it will assign the whole object to the model and not the property.
The problem with this approach is, that you cannot just compare objects (because comparing an object always compares their reference, not the "contents", so that obj1 == obj2 will never be true, unless they are exact the same object), so the other trick needed here is to use track by <some-id-property> on the ng-options. So your editable would look like this:
<span editable-select="data.organisation.OrganisationType"
e-ng-options="type as type.Name for type in data.types track by type.Id">
{{data.organisation.OrganisationType.Name}}
</span>
Beware that on your JSFiddle you're using a very old version of angular (where track by is not supported), so I created a new one using 1.2, which is the oldest angular version supporting track by:
http://jsfiddle.net/NBhn4/170/

ng-options predefined option Object

Have a look at my example
http://plnkr.co/edit/21ewxVIaRm4IHyF3TgoD?p=preview
I need the option object to be stored as ng-model so i use for ng-options ng-options="m as m.name for m in list"
However, if i set ng-model manually as the object it does not select the correct option in the dropdown list by default. It stores the data correctly, but it only pre-selects an option if use this expression ng-options="m.name as m.name for m in list" but this stores a string on the model instead of the options object.
Am I doing something incorrectly?
Goal:
set ng-model to the default option object and have it be automatically selected in the dropdown.
Updated plunker.
For the version you are using (1.0.8), you would have to resolve the object using a loop:
$scope.selected = {
name:"Something"
}
$scope.setSelected = function() {
angular.forEach($scope.list, function(item) {
if (item.name == $scope.selected.name) {
$scope.selected = item;
}
})
}
$scope.setSelected();
More recent versions, have track by syntax supported in the ng-options. So you could write:
ng-options="m.name for m in list track by m.name"
And this would set the object that matches the predicate.
As Davin Tryon has already mentioned, using track by is the correct way of doing it, however, I see some people using track by and 'as' in the same ng-options string, which will not work. using track by should also cater the need of using 'as'

Resources