{"action":"closed","issue":{"url":"https://api.github.com/repos/angular/angular.js/issues/11930","labels_url":"https://api.github.com/repos/angular/angular.js/issues/11930/labels{/name}","comments_url":"https://api.github.com/repos/angular/angular.js/issues/11930/comments","events_url":"https://api.github.com/repos/angular/angular.js/issues/11930/events","html_url":"https://github.com/angular/angular.js/issues/11930","id":79494354,"number":11930,"title":"ngOptions incorrectly evaluates label for $$hashKey when watching labels","user":{"login":"ryanhart2","id":5890155,"avatar_url":"https://avatars.githubusercontent.com/u/5890155?v=3","gravatar_id":"","url":"https://api.github.com/users/ryanhart2","html_url":"https://github.com/ryanhart2","followers_url":"https://api.github.com/users/ryanhart2/followers","following_url":"https://api.github.com/users/ryanhart2/following{/other_user}","gists_url":"https://api.github.com/users/ryanhart2/gists{/gist_id}","starred_url":"https://api.github.com/users/ryanhart2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ryanhart2/subscriptions","organizations_url":"https://api.github.com/users/ryanhart2/orgs","repos_url":"https://api.github.com/users/ryanhart2/repos","events_url":"https://api.github.com/users/ryanhart2/events{/privacy}","received_events_url":"https://api.github.com/users/ryanhart2/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/angular/angular.js/labels/branch:%201.4.x","name":"branch: 1.4.x","color":"fad8c7"},{"url":"https://api.github.com/repos/angular/angular.js/labels/component:%20forms","name":"component: forms","color":"7B947B"},{"url":"https://api.github.com/repos/angular/angular.js/labels/severity:%20regression","name":"severity: regression","color":"e11d21"},{"url":"https://api.github.com/repos/angular/angular.js/labels/type:%20bug","name":"type: bug","color":"000000"}],"state":"closed","locked":false,"assignee":{"login":"petebacondarwin","id":15655,"avatar_url":"https://avatars.githubusercontent.com/u/15655?v=3","gravatar_id":"","url":"https://api.github.com/users/petebacondarwin","html_url":"https://github.com/petebacondarwin","followers_url":"https://api.github.com/users/petebacondarwin/followers","following_url":"https://api.github.com/users/petebacondarwin/following{/other_user}","gists_url":"https://api.github.com/users/petebacondarwin/gists{/gist_id}","starred_url":"https://api.github.com/users/petebacondarwin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/petebacondarwin/subscriptions","organizations_url":"https://api.github.com/users/petebacondarwin/orgs","repos_url":"https://api.github.com/users/petebacondarwin/repos","events_url":"https://api.github.com/users/petebacondarwin/events{/privacy}","received_events_url":"https://api.github.com/users/petebacondarwin/received_events","type":"User","site_admin":false},"milestone":{"url":"https://api.github.com/repos/angular/angular.js/milestones/95","html_url":"https://github.com/angular/angular.js/milestones/1.4.1","labels_url":"https://api.github.com/repos/angular/angular.js/milestones/95/labels","id":1136484,"number":95,"title":"1.4.1","description":"","creator":{"login":"matsko","id":93018,"avatar_url":"https://avatars.githubusercontent.com/u/93018?v=3","gravatar_id":"","url":"https://api.github.com/users/matsko","html_url":"https://github.com/matsko","followers_url":"https://api.github.com/users/matsko/followers","following_url":"https://api.github.com/users/matsko/following{/other_user}","gists_url":"https://api.github.com/users/matsko/gists{/gist_id}","starred_url":"https://api.github.com/users/matsko/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/matsko/subscriptions","organizations_url":"https://api.github.com/users/matsko/orgs","repos_url":"https://api.github.com/users/matsko/repos","events_url":"https://api.github.com/users/matsko/events{/privacy}","received_events_url":"https://api.github.com/users/matsko/received_events","type":"User","site_admin":false},"open_issues":7,"closed_issues":6,"state":"open","created_at":"2015-05-27T17:23:41Z","updated_at":"2015-06-04T05:29:00Z","due_on":"2015-06-05T07:00:00Z","closed_at":null},"comments":2,"created_at":"2015-05-22T15:21:43Z","updated_at":"2015-06-04T05:29:00Z","closed_at":"2015-06-04T05:29:00Z","body":"**Overview of the Issue**\r\nWithin a directive, there is a variable on the scope which is an array of arrays. The directive template uses ng-repeat to repeat a `<select>` for each of the \"child\" arrays in this array variable. Each `<select>` has an ng-options attribute with the format *\"item as translate(item) for item in array\"* where array is provided by the ng-repeat and translate is a function on the scope that translates the item value for display.\r\nAt this point the array provided by ng-repeat has a $$hashkey property. This property is correctly omitted from the options on the `<select>`, however, the translate function is invoked for this property in addition to the other items in the array, which is not expected.\r\n\r\n**Motivation for or Use Case**\r\nThe motivation is to have a directive that can be provided with an array of selections that the user is required to make, with each selection variable being an array of the available options. The directive will then display a select element for each selection containing the relevant options. The directive accepts an optional translate-options attribute which, when set to true, will result in the options being translated. The translation should only affect the display of the options and not the model value.\r\n\r\n**Angular Version(s)**\r\nThis issue does *not* occur with version 1.3.15\r\nThis issue *does* occur with versions 1.4.0-beta.0 through to at least 1.4.0-rc.2\r\n\r\n**Browsers and Operating System**\r\nChrome  43.0.2357.65 m, Windows 8.1\r\n\r\n**Reproduce the Error**\r\nhttp://plnkr.co/edit/nyOOCbqcz3QlPvjddW3R?p=preview\r\n\r\n**Related Issues**\r\nNone\r\n\r\n**Suggest a Fix**\r\nWhen `Object.keys(values).forEach` is executed below, `values` has a $$hashKey property which is then passed in to the getWatchable function. This results in displayFn being invoked with the locals parameter being an object with a value similar to {value: \"object:50\"}. A potential fix is for the getWatchable function to ignore keys that begin with '$$'.\r\n```\r\ngetWatchables: $parse(valuesFn, function(values) {\r\n  // Create a collection of things that we would like to watch (watchedArray)\r\n  // so that they can all be watched using a single $watchCollection\r\n  // that only runs the handler once if anything changes\r\n  var watchedArray = [];\r\n  values = values || [];\r\n\r\n  Object.keys(values).forEach(function getWatchable(key) {\r\n    var locals = getLocals(values[key], key);\r\n    var selectValue = getTrackByValueFn(values[key], locals);\r\n    watchedArray.push(selectValue);\r\n\r\n    // Only need to watch the displayFn if there is a specific label expression\r\n    if (match[2] || match[1]) {\r\n      var label = displayFn(scope, locals);\r\n      watchedArray.push(label);\r\n    }\r\n\r\n    // Only need to watch the disableWhenFn if there is a specific disable expression\r\n    if (match[4]) {\r\n      var disableWhen = disableWhenFn(scope, locals);\r\n      watchedArray.push(disableWhen);\r\n    }\r\n  });\r\n  return watchedArray;\r\n})\r\n```"}}