I have a select control. Its options are generated dynamically from scope's array of objects. On app init I want to select a specific option by changing bound variable on the scope.
It doesn't work when select's ng-option returns full object. However, it works when select's ng-option returns string.
Is it angular bug or I do something wrong?
HTML:
<div ng-controller="selectCtrl" ng-app>
Doesn't work when select's ngModel value is object:<br />
<select ng-model="valueObject" ng-options="o.label for o in options"></select><br />
<pre>{{valueObject | json}}</pre>
Works when select's ngModel value is string:<br />
<select ng-model="valueString" ng-options="o.value as o.label for o in options"></select>
<pre>{{valueString | json}}</pre>
JS:
function selectCtrl($scope) {
$scope.options = [
{label: 'a', value: '1', someId: 333},
{label: 'b', value: '2', someId: 555}
];
$scope.valueObject = {label: 'a', value: '1', someId: 333};
$scope.valueString = '1';
};
JS Fiddle: /
I have a select control. Its options are generated dynamically from scope's array of objects. On app init I want to select a specific option by changing bound variable on the scope.
It doesn't work when select's ng-option returns full object. However, it works when select's ng-option returns string.
Is it angular bug or I do something wrong?
HTML:
<div ng-controller="selectCtrl" ng-app>
Doesn't work when select's ngModel value is object:<br />
<select ng-model="valueObject" ng-options="o.label for o in options"></select><br />
<pre>{{valueObject | json}}</pre>
Works when select's ngModel value is string:<br />
<select ng-model="valueString" ng-options="o.value as o.label for o in options"></select>
<pre>{{valueString | json}}</pre>
JS:
function selectCtrl($scope) {
$scope.options = [
{label: 'a', value: '1', someId: 333},
{label: 'b', value: '2', someId: 555}
];
$scope.valueObject = {label: 'a', value: '1', someId: 333};
$scope.valueString = '1';
};
JS Fiddle: http://jsfiddle.net/apuchkov/FvsKW/6/
Share Improve this question edited Sep 29, 2015 at 11:51 John Slegers 47.1k23 gold badges204 silver badges173 bronze badges asked Sep 27, 2013 at 18:38 Alexander PuchkovAlexander Puchkov 5,9734 gold badges37 silver badges49 bronze badges3 Answers
Reset to default 10"Track by" expression has to be used to make example in my question work. More details here: http://leoshmu.wordpress.com/2013/09/11/making-the-most-of-ng-select/
Updated JsFiddle: http://jsfiddle.net/apuchkov/FvsKW/9/
HTML
<div ng-controller="selectCtrl" ng-app>
Doesn't work when select's ngModel value is object:<br />
<select ng-model="valueObject" ng-options="o.label for o in options"></select><br />
<pre>{{valueObject | json}}</pre>
Does work when select's ngModel value is object AND 'track by' expression is used:<br />
<select ng-model="valueObject" ng-options="o.label for o in options track by o.value"></select><br />
<pre>{{valueObject | json}}</pre>
</div>
JS
function selectCtrl($scope) {
$scope.options = [
{label: 'a', value: '1', someId: 333},
{label: 'b', value: '2', someId: 555}
];
$scope.valueObject = {label: 'a', value: '1', someId: 333};
};
The key is that objects with the same keys and values are not equal to each other (ref ES 5.1 Specification 11.9.6):
// Return true if x and y refer to the same [in-memory] object.
// Otherwise, return false.
> var one = {label: 'a', value: '1', someId: 333}
> var two = {label: 'a', value: '1', someId: 333}
> one === one
true
> two === two
true
> one === two
false
> one == two
false
Change $scope.valueObject = { /* similar object */ }
to $scope.valueObject = $scope.options[0]
and everything should work.
It should work for such controller:
function selectCtrl($scope) {
$scope.options = [
{label: 'a', value: '1', someId: 333},
{label: 'b', value: '2', someId: 555}
];
$scope.valueObject = $scope.options[ 0 ];
};