Search code examples
angularjsangular-ngmodelangularjs-ng-clickangularjs-ng-change

AngularJS: ng-change does not work when value changes on ng-click


I have created some control buttons to handle server side pagination. It has 4 buttons (First Page, Previous Page, Next Page and Last Page), a page counter which is an input text field and a drop-down to select a number of rows you want to see.

The page counter is defined as vm.currentPage in the controller, which can be manipulated by the buttons or typing a new value in the input, and the drop-down as vm.rowsPerPage. For both these elements I have declared a ng-change with a function inside that eventually has to get the data, called vm.setPagingData();

My problem here is that this function is not getting fired when I use one of the control buttons, even though vm.currentPage inside the input text is changing.

There is no problem when I directly change the value in the input or when I use the dropdown to select a number of rows I want to see.

Below I have a sample code with the function setPagingData() incrementing a value by 1 every time it been called. Plnkr link: http://plnkr.co/edit/qHrTC9gkntSw9IfgeJ5T?p=preview

html:

<!--Back Buttons-->
<button ng-disabled="ctrl.currentPage <= 1" ng-click="ctrl.currentPage = 1;"> << </button>
<button ng-disabled="ctrl.currentPage <= 1" ng-click="ctrl.currentPage = ctrl.currentPage - 1"> < </button>

<!--Current page count-->
<span><input type="text" ng-model="ctrl.currentPage" ng-change="ctrl.setPagingData()" /> of {{ctrl.totalPages}}</span>

<!--Next buttons-->
<button ng-disabled="ctrl.currentPage >= ctrl.totalPages" ng-click="ctrl.currentPage = ctrl.currentPage + 1;"> > </button>
<button ng-disabled="ctrl.currentPage >= ctrl.totalPages" ng-click="ctrl.currentPage = ctrl.totalPages;"> >> </button>

<br><br>

    Show:
    <select ng-model="ctrl.rowsPerPage" ng-change="ctrl.setPagingData()">
        <option value="10" ng-selected="ctrl.rowsPerPage === '10'">10 rows</option>
        <option value="20" ng-selected="ctrl.rowsPerPage === '20'">20 rows</option>
        <option value="40" ng-selected="ctrl.rowsPerPage === '40'">40 rows</option>
        <option value="60" ng-selected="ctrl.rowsPerPage === '60'">60 rows</option>
    </select>

<br><br>
{{ctrl.test}}

controller:

vm.currentPage = 1;
vm.totalPages = 16;
vm.rowsPerPage = "20";

vm.test = 0;

vm.setPagingData = function(){
  vm.test++;
}

Should I define the logic of the buttons inside controller instead of inside the ng-change or something? Or is there a way to keep it in the HTML?


Solution

  • As described in the documentation, ng-change is triggered when the user changes the value of the input field manually.

    Available solutions:

    Using ngClick

    Call ctrl.setPagingData() inside the ng-click of your buttons

    <button ng-click="ctrl.currentPage = ctrl.currentPage + 1; ctrl.setPagingData();" ng-disabled="ctrl.currentPage >= ctrl.totalPages"> > </button>
    <button ng-click="ctrl.currentPage = ctrl.totalPages; ctrl.setPagingData();" ng-disabled="ctrl.currentPage >= ctrl.totalPages"> >> </button>
    

    Using $scope.$watch

    Watch for changes to the variable vm.rowsPerPage:

    $scope.$watch(function() {
      return vm.rowsPerPage;
    }, function() {
      vm.setPagingData();
    });