Mano Faria
Mano Faria

Reputation: 13

ng-options nested in ng-repeat

I'm having the angular feature issue where my select list has an empty first option, but this situation is a little different from the research I've done online. When I place the select tag outside of the ng-repeat, there is no blank option as the default selected value. When I place the select tag using the ng-option attribute within the ng-repeat, I have the blank issue. I've tried setting the default value for the ng-model attribute on the select tag with no luck. Here is the html fragment:

<tr ng-repeat="item in todo.items">
  <td>{{item.project}}</td>
  <td>{{item.action}}</td>
  <td>
    <select ng-model="ttdSelect" ng-change="moveItem(item.id, ttdSelect);" ng-options="option.name for option in todo.options track by option.name">    
    </select>
  </td>
</tr>

javascript:

var items = [{"id" : 1, "name" : "ttd" , "action" : "do it"}];

var selectOptions = [{ "name" : "next", "value" : "nextUp"},
                       { "name" : "in progress", "value" : "inProgress"},
                       { "name" : "waiting", "value" : "waiting"},
                       { "name" : "done", "value" : "done"},
                       { "name" : "trash", "value" : "trash"}];

app.controller("appController", function ($scope)
{
  $scope.todo.items = items;
  $scope.todo.options = selectOptions;
}

Upvotes: 0

Views: 941

Answers (2)

beaver
beaver

Reputation: 17647

Similar to the answer of jusopi but here in a SO snippet:

var app = angular.module('myApp', []);

var items = [{
  "id": 1,
  "name": "ttd",
  "action": "do it"
},
{
  "id": 2,
  "name": "zzz",
  "action": "do it 2"
}];

var selectOptions = [{
  "name": "next",
  "value": "nextUp"
}, {
  "name": "in progress",
  "value": "inProgress"
}, {
  "name": "waiting",
  "value": "waiting"
}, {
  "name": "done",
  "value": "done"
}, {
  "name": "trash",
  "value": "trash"
}];

app.controller("appController", function($scope) {
  $scope.todo = {};
  $scope.todo.items = items;
  $scope.todo.options = selectOptions;
  
  angular.forEach($scope.todo.items, function(item, key) {
    item.ttdSelect = $scope.todo.options[0];
  });
});
<!DOCTYPE html>
<html ng-app="myApp">
<head>
  <meta charset="utf-8" />
  <script data-require="[email protected]" src="https://code.angularjs.org/1.4.8/angular.js" data-semver="1.4.8"></script>
  <script src="app.js"></script>
</head>
<body ng-controller="appController">
  <div>
    <table class="table">
      <tr ng-repeat="item in todo.items">
        <td>{{item.project}}</td>
        <td>{{item.action}}</td>
        <td>
          <select ng-model="item.ttdSelect" 
          ng-change="moveItem(item.id, item.ttdSelect);" 
          ng-options="option.name for option in todo.options track by option.name">
          </select>
        </td>
      </tr>
    </table>
    <b>Trace:</b>
    <pre>
  items = {{todo.items | json}}
  </pre>
    <pre>
  options = {{todo.options | json}}
  </pre>
  </div>
</body>
</html>

Upvotes: 1

jusopi
jusopi

Reputation: 6813

I had a hard time following what exactly it is that you wanted so I tried to do it the way I'd normally tackle a problem like this.

example - http://codepen.io/jusopi/pen/PZzxPY

There are a few problems I addressed in reworking your code:

  • ttdSelect was not pointing to anything in your code. I assumed you meant to update the status value of the todo item so I assigned it to item.status
  • I created a status option to match a falsy value when a todo item doesn't have a current status
  • I demonstrated that you can actually bypass ng-options on the <select> and instead use ng-repeat on the <option> element instead to make it a little easier to read.

I hope this helps. Keep in mind I did this in jade/coffeescript because I work faster and better that way. You can easily see the compiled html/js if you need to.

Upvotes: 0

Related Questions