AngularJS ngOptions track by does not set entire object to ngModel

431 Views Asked by At

Here my json object :

 $scope.todos = [{
    name: 'angular',
    field: ['a', 'b', 'c', 'd'],
    id: 1
  }, {
    name: 'asd',
    field: ['a', 'b', 'c', 'd', 'e'],
    id: 2
  }];

I give select as :

<select ng-model="dashboard.type" ng-options="item as item.name for item in todos track by item.name"></select>

Now when an option is chosen i want another select which iterates upon ngModel of previous select. The next looks like :

<select ng-model="dashboard.label" ng-options="item as item for item in dashboard.type.field"></select>

It works fine when i choose the option manually but when their is a value in dashboard.type (eg: $scope.dashboard.type.name = 'qwe') in my script, it uses track by to choose the option and save it in dashboard.type, instead of saving the entire object it just saves the value used in track by option.

Value for dashboard.type:

  1. when i choose option manually : {"name":"qwe","field":["a","b","c","d","f"],"id":3}
  2. When track by is used : {"name":"qwe"}

NOTE: I cannot use track by item . It has to be a property of the object item. It can either be name or id.

Here's a plnkr.

Edit :

As pointed out by many, i would like to clarify that I can not initialise the object to any value of todos list. This is because dashboard.type.name value would be different every single time and todos list vary from 10 to 100's of objects. Now I have to iterate the list todos check if todos[index].name==someName and assign the relevant object. I am actively trying to avoid this soution (because there has to be a better way).

NOTE : I also tried using ng-change and assign the actual object to dashboard.type.name but that works only when option is selected manually ,which already seems to be working fine. It does not assign the object when track by is used.

IMPORTANT: $scope.dashboard.type.name = 'qwe' is just an example. Value of $scope.dashboard.type.name may change every single time the page is loaded.

PS: Also i should have mentioned this earlier.Sorry, My bad!

3

There are 3 best solutions below

0
On

This issue is not because of track by. Setting a default value by doing $scope.dashboard.type.name = 'qwe', causes ng-model to look like $scope.dashboard.type = {name : 'qwe'}. Instead of selecting the default value this way, you should use $scope.dashboard.type = $scope.todos[2];. This will make sure the entire object is set to $scope.dashboard.type.

Edited plunker

0
On

To initialize the modal by a default value you can use ng-init. For example

 <select ng-init="dashboard.type = todos[2]" ng-model="dashboard.type" ng-options="item as item.name for item in todos track by item.name">
  </select>
3
On

call this function on ng-init in html

ng-init ="initialize();"

in js

$scope.dashboard={};//initialize object
$scope.dashboard.type ={}//initialize object

$scope.initialize =function(){


//no need to iterate if it is certain that your Id and index is always same suppose your initial id is 3

//then
var currId =3;//suppose initial id is there
$scope.dashboard.type =$scope.todos[currId]

}

here is codepen for it http://codepen.io/vkvicky-vasudev/pen/MeexmK