简体   繁体   中英

Angular: select ng-model programmatically changed but ng-change event doesn't fire

Here's my select element:

 <select class="small-3 columns end statSelect"
          ng-model="chart.categoryAxis"
          ng-change="renderMainChart()"
          ng-options="metric as metric.value for metric in chart.metrics()">
  </select>

I'm changing chart.categoryAxis programmatically every time I click on a button. However, the ng-change method renderMainChart() doesn't get called. Why is this?

Here's an example of one of the options:

<option label="Ad Started" value="object:33">Ad Started</option>

Depending on which button I click, that changes the ng-model value appropriately. But the ng-change function renderMainChart() doesn't get called.

Aelliott1485's answer can be implemented but it would need you to add an extra watch which may not be preferable always.


If you are using Angular 1.3 or higher then you can pass a function to the ng-model directive.

This allows you to specify a method instead of a variable in your ng-model attribute. The method should take an optional parameter. If an argument is passed it should store that value, if no argument is passed it should return a value.

In this case change your ng-model to call a function instead of accessing a property.

<select class="small-3 columns end statSelect"
      ng-model="chart.categoryAxis()"
      ng-change="renderMainChart()"
      ng-options="metric as metric.value for metric in chart.metrics()">    
</select>

and write a function like this in your controller

$scope.categoryAxis = function(value) {
    $scope.ca = value || $scope.ca; // You can also keep a local variable inside the controller instead of a property on $scope
    return $scope.ca;
};

NOTE: You may need to come up with better names.

You can utilize $watch() to handle the changing of the value, even when the user doesn't change the value using the select list. For example:

 var app = angular.module('plunker', []); app.controller('MainCtrl', function($scope) { var options = [{ value: 'a', id: 1 }, { value: 'b', id: 2 }]; $scope.debugOutput = ''; $scope.chart = { categoryAxis: options[0], metrics: function() { return options; } }; $scope.renderMainChart = function() { console.log('renderMainChart', arguments); }; $scope.pickA = function() { $scope.chart.categoryAxis = options[0]; }; $scope.pickB = function() { $scope.chart.categoryAxis = options[1]; }; $scope.$watch('chart.categoryAxis', function(newValue, oldValue) { $scope.debugOutput += 'categoryAxis changed ' + angular.toJson(oldValue) + ' to ' + angular.toJson(newValue) + "\\n"; }); }); 
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <div ng-app="plunker"> <div ng-controller="MainCtrl"> <select class="small-3 columns end statSelect" ng-model="chart.categoryAxis" ng-change="renderMainChart()" ng-options="metric as metric.value for metric in chart.metrics()"></select> <div>Selected category Axis: <span>{{ chart.categoryAxis | json }}</span></div> <div> <input type="button" ng-click="pickA()" value="pickA" /> </div> <div> <input type="button" ng-click="pickB()" value="pickB" /> </div> <div>{{ debugOutput }}</div> </div> </div> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM