Reputation: 746
It is easy to use Angular data binding to force a JavaScript property to change when a user changes the item selected in a menu. However, I cannot figure out how to force a data bound property to change when the model used to generate a menu changes.
This fiddle demonstrates the behavior: http://jsfiddle.net/2pHGX/. Changing the model by clicking changeOptions causes the select options to change correctly. But the data bound property does not change immediately, it only changes when the user selects a different menu option.
<body ng-app ng-controller="bodyCtrl">
<select ng-model="selection" ng-options="option for option in options">
</select>
<button ng-click="changeOptions()">changeOptions</button>
<br>
selection: {{selection}}
</body>
function bodyCtrl($scope) {
$scope.options = [10, 20, 30];
$scope.changeOptions = function() {
$scope.options = [11, 22, 33];
};
}
I want the data bound property to update when the selected option changes for any reason, either because the user picked a different option or because the model, and therefore options, changed. I can make this work with $watch
, but I cannot understand why data binding alone is not sufficient. What is the best way to accomplish this with Angular? Am I misunderstanding something fundamental about data binding?
Upvotes: 3
Views: 14187
Reputation: 4570
If you directly bind ng-model to a scope variable as below, the scope variable somehow will not be updated.
<select ng-model="selection" ng-options="option for option in options">
Instead, define a view model in your scope and bind ng-model to a field of view model the view model field will be updated.
<select ng-model="viewmodel.selection" ng-options="option for option in options">
In your controller, you should do this:
app.controller('SomeCtrl', ['$scope'
function($scope)
{
$scope.viewmodel = {};
});
Upvotes: 5
Reputation: 67336
I'm not sure the exact behaviour that you want, but you can always watch options and, therefore, on change take an action (JSFiddle):
function bodyCtrl($scope) {
$scope.selection = 0;
$scope.options = [ 10, 20, 30];
$scope.changeOptions = function() {
$scope.options = [11, 22, 33];
};
$scope.$watch('options', function() {
$scope.selection = 0;
});
}
Hope this helps.
Upvotes: 2