admin管理员组文章数量:1410737
So I have a controller like this
app.controller("ReservationCtrl", function($scope) {
$scope.rooms = [{id: 1, name: "Room 1"}, {id: 2, name: "Room 2", }];
$scope.reservation = {id: 1, time: "9AM", room: {id: 2, name: "Room 2"}};
});
A view that looks like this:
<select ng-model="reservation.room" ng-options="room as room.name for room in rooms"></select>
The problem is that the select box won't bind to the correct room unless I say
$scope.reservation.room = $scope.rooms[1];
This is rather inconvenient for development as the room is not the only field on the reservation
model that needs to be bound to a select box. How can I apply the binding without doing this extra step?
Also, the binding breaks again if I do something like
$http.get("/reservation/2").success(function(data) { $scope.reservation = angular.copy(data); });
So I have a controller like this
app.controller("ReservationCtrl", function($scope) {
$scope.rooms = [{id: 1, name: "Room 1"}, {id: 2, name: "Room 2", }];
$scope.reservation = {id: 1, time: "9AM", room: {id: 2, name: "Room 2"}};
});
A view that looks like this:
<select ng-model="reservation.room" ng-options="room as room.name for room in rooms"></select>
The problem is that the select box won't bind to the correct room unless I say
$scope.reservation.room = $scope.rooms[1];
This is rather inconvenient for development as the room is not the only field on the reservation
model that needs to be bound to a select box. How can I apply the binding without doing this extra step?
Also, the binding breaks again if I do something like
$http.get("/reservation/2").success(function(data) { $scope.reservation = angular.copy(data); });
Share
Improve this question
asked Sep 19, 2015 at 18:48
kshep92kshep92
8951 gold badge11 silver badges25 bronze badges
4 Answers
Reset to default 3I think this is because,
in your ng-options
if you select an option, the selected value is an object
EX: if you select first option then model value is an object which is the first element in the $scope.rooms
({id: 1, name: "Room 1"}
).
objects are reference type data type. So what it does is if the objects create one time then all of its usage are pointing to that object. have a look at this article.
So your selected value is an object which is a reference type. In your case you have two independent objects for the $scope.reservation.room
and the {id: 2, name: "Room 2"}
which is in rooms
array. note that they are in separated memory slots.
In your working case both of the $scope.reservation.room
and the {id: 2, name: "Room 2"}
which is in rooms
array are pointing to same memory slot because you have equals the two as $scope.reservation.room = $scope.rooms[1];
This means $scope.reservation.room
& $scope.rooms[1]
both are pointing to the same object in the memory.
To work this out you can do something different than your working solution.
change the ng-repeat
as following
...ng-options="room.id as room.name for room in rooms"...
and change the ng-model
....ng-model="reservation.id"....
this will select the id
of the option as the selected value for EX if you select the first option then the model value will be 1
which is the id
of the first option.
in this case selected model values are primitive(like 1,2,3..
) type data then its not going to search for the objects in memory instead it will get the value of stack and check with the option values and select the correct one.
here is a DEMO this will select the second option initially.
------------------------------------------------- SUMMARY -------------------------------------------------
If the selected model value is an object
then it will check the memory address of the selected object and the all objects of the $scope.rooms
and check if there is a matching element and select the matching option if one is found. if no one found then nothing will select.
If the model values are primitive like 1,2,3..
it will search the value and check if there any matching option
value
if one is found it will select that option.
So it seems the key to this problem is the track by
clause in the ng-options
directive. See my updated fiddle
As you will see, the whole model is being updated and not just its ID. The documentation says that select as
and track by
were not meant to be used together, but the example they used to illustrate this is a bit different from mine.
Since I've received no feedback from the official Angular channels on this matter to date, I'm gonna mark this as solved and move on.
Thanks for the help everyone.
When the view is loaded, the select box has no selected value because the room object in $scope.reservation
is not the same object as the one in $scope.rooms
, event if it has the same values.
Thats why your example does not work (fiddle)
But this one works:
$scope.rooms = [{id: 1, name: "Room 1"}, {id: 2, name: "Room 2"}];
$scope.reservation = {
id: 1,
time: "9AM",
room: $scope.rooms[1] // <-- now the reservation room references a valid ng-repeated room
};
See updated fiddle
To avoid problems, I'll suggest you bind to the variable of your select box only the room id of the reservation. Because it is a primitive type, the parison will be made by value, and that will solve also your second use case. Moreover, you better not duplicate data in the reservation object. See fiddle
If you need to display the name of the reserved (selected) room, you could easily write a getRoomById
function that will look into the array of rooms.
Change the scope only when the value changes.
if($scope.reservation.room != $scope.rooms[1])
$scope.reservation.room = $scope.rooms[1];
本文标签: javascriptAngularJS Select box not updating when model is changedStack Overflow
版权声明:本文标题:javascript - AngularJS Select box not updating when model is changed - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744329930a2600914.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论