Chris
Chris

Reputation: 746

AngularJS: Updating ngModel property when select options change

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

Answers (2)

Yang Zhang
Yang Zhang

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

Davin Tryon
Davin Tryon

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

Related Questions