Object.keys () does not work in ng-options

advertisements

I am trying to create a dropdown list using ng-options:

<!DOCTYPE html>
<html ng-app="m1">
  <head>
    <script src='https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js'></script>
  </head>
  <body ng-controller="c1">
    <div>
      Sort1
      <select ng-model="sortKey1">
        <option value="bookId">By Id</option>
        <option value="bookTitle">By Title</option>
        <option value="cost">By Cost</option>
      </select>
    </div>
    <div>
      Sort2
      <select ng-model="sortKey2" ng-options="x for x in Object.keys(books[0])">
      </select>
    </div>
    <div>
      Sort3
      <select ng-model="sortKey3" ng-options="x for x in bookKeys">
      </select>
    </div>
  </body>
  <script type="text/javascript">
    var m1 = angular.module("m1", []);

    m1.controller('c1',function($scope)
    {
      $scope.books = [
      {
          "bookId": 101,
          "bookTitle": "Angular JS",
          "cost":375,
      },
      {
          "bookId": 102,
          "bookTitle": "Instant AngularJS Starter",
          "cost":150,
      },
      {
          "bookId": 103,
          "bookTitle": "Ng-Book: The Complete Book on AngularJS",
          "cost":4657,
      }];

      console.log(Object.keys($scope.books[0]));
      $scope.bookKeys = Object.keys($scope.books[0]);
    });
  </script>
</html>

I am trying to get the dropdown values from an object's keys by calling Object.keys() on an object and then using the resultant array in ng-options.

I am trying to create the effect of case 1. My attempt at case 2 is not working, however a similar thing implemented in case 3 is working.

Can anybody tell the reason why case 2 is not working?


Update
As indicated in Zen's answer, the reason Object.keys() does not work in ng-repeat is due to the context in which it is evaluated (that being the context of $scope).

Angular has this functionality built in in the form of (key, val). Sometimes the support for native javascript functions within an Angular express is limited and in this instance Angular probably doesn't understand Object.keys() as the source for ng-options. Change the <select> in your case 2 to:

<select ng-model="sortKey2" ng-options="key as key for (key,val) in books[0]">

Working example:

    var m1 = angular.module("m1", []);

    m1.controller('c1', function($scope) {
      $scope.books = [{
        "bookId": 101,
        "bookTitle": "Angular JS",
        "topic": "AngularJS",
        "author": "Green",
        "cost": 375,
      }, {
        "bookId": 102,
        "bookTitle": "Instant AngularJS Starter",
        "topic": "AngularJS",
        "author": "Dan Menard",
        "cost": 150,
      }, {
        "bookId": 103,
        "bookTitle": "Ng-Book: The Complete Book on AngularJS",
        "topic": "AngularJS",
        "author": "Ari Lerner",
        "cost": 4657,
      }];

      console.log(Object.keys($scope.books[0]));
      $scope.bookKeys = Object.keys($scope.books[0]);
    });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.min.js"></script>
<div ng-app="m1" ng-controller="c1">
  <div>
    Sort1
    <select ng-model="sortKey1">
      <option value="bookId">By Id</option>
      <option value="bookTitle">By Title</option>
      <option value="topic">By Topic</option>
      <option value="author">By Author</option>
      <option value="cost">By Cost</option>
    </select>
  </div>
  <div>
    Sort2
    <select ng-model="sortKey2" ng-options="key as key for (key,val) in books[0]">
    </select>
  </div>
  <div>
    Sort3
    <select ng-model="sortKey3" ng-options="x for x in bookKeys">
    </select>
  </div>
</div>

EDIT: (applied to answer) If you want the value of a select option to not become the value of the object (for eg. 101, AngularJS etc.), you can write <select ng-model="sortKey2" ng-options="key as key for (key,val) in books[0]">