Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't set selected value of ng-options

I am trying to populate a drop-down select options list and set a default selected value using ng-model and ng-options.

I have the following code in my view:

<select ng-model="thisTour.site" ng-options="site.name for site in siteList"></select>

And in my controller:

    $scope.siteList = [
        { id: 1, name: 'cycling'},
        { id: 2, name: 'walking'},
        { id: 3, name: 'holidays'}
    ]

    $scope.thisTour.site = { id: 2, name: 'walking'};

The list is getting populated with the correct 3 options from the siteList object, but it is not selecting walking by default as I would expect? Why not?

Now, when I change this:

$scope.thisTour.site = { id: 2, name: 'walking'};

To this:

$scope.thisTour.site = $scope.siteList[1];

Now it works. Why? Isn't it the same thing?

like image 547
Inigo Avatar asked Dec 16 '14 21:12

Inigo


People also ask

How do I set default selected value in ng-options?

In my opinion the correct way to set a default value is to simply pre-fill your ng-model property with the value selected from your ng-options , angular does the rest. Essentially when you define the $scope property your select will bind to assign it the default value from your data array.

How do you use NG value?

The AngularJS ng-value directive is used to set the value attribute of an input element, or a select element. It is mainly used on <radio> and <option> elements to set the bound values when these elements are selected. It is supported by <input> and <select> elements.

How do ng-options work?

Definition and Usage. The ng-options directive fills a <select> element with <options>. The ng-options directive uses an array to fill the dropdown list. In many cases it would be easier to use the ng-repeat directive, but you have more flexibility when using the ng-options directive.

What is Ng selected?

Definition and Usage The ng-selected directive sets the selected attribute of an <option> element in a <select> list. The option will be selected if the expression inside the ng-selected attribute returns true. The ng-selected directive is necessary to be able to shift the value between true and false .

What is the use of ng options in angular?

AngularJS ng-options Directive 1 Definition and Usage. The ng-options directive fills a <select> element with <options>. The ng-options directive uses an... 2 Syntax. Supported by the <select> element. 3 Parameter Values. An expression that selects the specified parts of an array to fill the select element. More ...

How does ng-select work with null as default option?

Using a default select this works as expected. Option is selected and model's value is set to null when selecting this option. Same situation here. Switching to ng-select from default <select> was a pain due to ignorance of 'null' as default option.

How to bind an option to an object using ngvalue?

For objects, use the ngValue input binding. Tracks the value bound to the option element. Unlike the value binding, ngValue supports binding to objects. Recently I have to build a dropdown for a simple yes/no input, which output is equivalent to a boolean type. Obviously, we can always use a checkbox for that purpose.

Why @input() ngvalue and ngvalue are always equal to any?

Because both "false" and "true" will always be truthy, which mean in the context of boolean, they are always equal true. @Input () ngValue: any: Tracks the value bound to the option element. Unlike the value binding, ngValue supports binding to objects. @Input () value: any: Tracks simple string values bound to the option element.


2 Answers

That is because angular looks for object equality to bind it with your syntax and inyour case $scope.siteList[1] is not equal to { id: 2, name: 'walking'}; (2 objects are equal only if they point to the same reference). You can get around this in many ways, one easy way is to use track by syntax with ng-options to specify track by id, which will enable ng-option's options to be tracked by the specified property of the bound object rather than the object reference itself.

<select ng-model="thisTour.site" 
    ng-options="site.name for site in siteList track by site.id"></select>

You could also use the syntax to minimally set the ng-model to specify only the id using select as part in the syntax:-

Example:-

ng-options="site.id as site.name for site in siteList"

and model would just be:-

 $scope.thisTour.site = 2;

angular.module('app', []).controller('ctrl', function($scope){
  $scope.thisTour = {};
 $scope.siteList = [
        { id: 1, name: 'cycling'},
        { id: 2, name: 'walking'},
        { id: 3, name: 'holidays'}
    ]

    $scope.thisTour.site = { id: 2, name: 'walking'};
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
  <select ng-model="thisTour.site" ng-options="site.name for site in siteList track by site.id"></select>
  {{thisTour.site}}
  </div>

From documentation

trackexpr: - Used when working with an array of objects. The result of this expression will be used to identify the objects in the array. The trackexpr will most likely refer to the value variable (e.g. value.propertyName). With this the selection is preserved even when the options are recreated (e.g. reloaded from the server).

Also worth noting:

Do not use select as and track by in the same expression. They are not designed to work together.

like image 163
PSL Avatar answered Nov 06 '22 02:11

PSL


This isn't the same thing because objects in javascript are passed by reference.

If you take the first example:

$scope.siteList = [
    { id: 1, name: 'cycling'},
    { id: 2, name: 'walking'},
    { id: 3, name: 'holidays'}
]

$scope.thisTour.site = { id: 2, name: 'walking'};

Then you do this:

$scope.thisTour.site.id = 3;
console.log($scope.siteList[1].id) // 2

In other words, whilst your two objects are equal in value, they aren't the same object. The ngOptions directive sees this, so would set thisTour.site to a blank value because it isn't one of the allowed options.

Google "passing by reference in javascript" to learn more.

like image 22
Ed_ Avatar answered Nov 06 '22 01:11

Ed_