-
Notifications
You must be signed in to change notification settings - Fork 27.4k
feat(select): New select attribute directive ng:hasher #1663
Conversation
Add new attribute directive for specifying a hashing function for objects. If ng:model is bound to an object and ng:options is "obj for obj in objs" a reference equality is used for selection. With ng:hasher you can bind a function that takes one argument and returns a hash. Then the hash is used for comparision instead. Ex. <select ng-model="selection" ng-options="obj for obj in objs" ng-hasher="hash_func"> </select> scope: { selection: { id: 12, ... } objs: [{ id: 12, ... }, { id: 13, ... } hash_func: function(o) { return o ? o.id : undefined; } } Will match model to the first obj in the objs array.
Yesterday I needed this functionality, and this would make my code much cleaner and simple 👍 |
This change can be achieved by: scope.hash_func = function() {}; ng-model="selection" So the new behavior just introduces a new way to do the same thing. For this reason we will not merge it in. If you feel otherwise feel free to reopen it and provide counter argument. |
@mhevery : no it is not the same. It will not run the hasher function on the selection/ng-model object, it will not select the object with id 12. I don't know how to reopen this, i'm a noob git user. |
What is wrong with object.id as object.label? |
Maybe a better example: $scope.person = { id:1, name:'Thomas', favorite_movie: { id:2, name: 'Startrek' } };
$scope.movies = [{ id: 1, name: 'Starwars' }, { id: 2, name: 'Startrek' }, { id: 3, name: 'Alien' }]; Without the hashing function i have to: <select ng-model="movieid" ng-options="movie.id as movie.name for movie in movies"></select> $scope.movieid = $scope.person.favorite_movie.id;
$scope.$watch('movieid', function() {
for(var i = 0; i < $scope.movies.length; i++)
if ($scope.movies[i].id == $scope.movieid)
$scope.person.favorite_movie = $scope.movies[i];
}); With the hashing function i could just write : <select ng-model="person.favorite_movie" ng-options="movie as movie.name for movie in movies" ng-hasher="moviehasher"></select> $scope.moviehasher = function(movie) { return movie ? movie.id : undefined; } |
What about I may not be clear on what you wanted but if I understand correctly, I only foresee a plethora of problems with this design:
It feels like it would create an unreliable and inconsistent behavior. Dean Sofer On Thursday, January 17, 2013 at 1:29 PM, quazzie wrote:
|
How about just changing select to use a deep compare rather than object equality? This would solve many problems that people have with selecting an object rather than an object's id. In the case of the example above:
This would just work:
As long as the properties on the person.favorite_movie matched the properties on an object in the movies array. |
Yeah what @petebacondarwin said is what i wanted, but i thought i'd be a bit more clever to allow for more configuration. |
The hashing function should be used with objects. If options is value-types hashing would be unnecessary. |
Im having the same problem. This functionality would be very interesting. |
I wrote another patch that does the same thing but in a diffrent way : #2040 |
Add new attribute directive for specifying a hashing function for objects.
If ng:model is bound to an object and ng:options is "obj for obj in objs"
a reference equality is used for selection.
With ng:hasher you can bind a function that takes one argument and returns
a hash. Then the hash is used for comparision instead.
Ex.
<select ng-model="selection" ng-options="obj for obj in objs" ng-hasher="hash_func"> /select>
Will match model to the first obj in the objs array.