javascriptangularjsangularjs-ng-repeatangularjs-ng-modelangularjs-ng-change

Fire ng-change when ng-model updated programmatically inside ng-repeat


I read topics related to this and found following, but still I am stuck.

How to $watch changes on models created by ng-repeat?

I am trying to implement plus, minus counter with following code. Now whenever ng-model updates either by clicking +/- button I want to fire ng-change. I understand that ng-change doesn't fire when the ng-model updated programatically. But the refrenced Stackoverflow has solution for that to add $watch on the ng-model. But its working if I create separate controller, not working inside current controller. ng-change is calling functions inside current controller. How to fix it??

<div class="input-group" ng-repeat="product in oc.itemdetail.lines">
    <input type="button" value="-" class="minus"
           ng-click="product.line.total = product.line.total - product.stepCount">

    <input  type="number"  ng-if="condition 1" ng-model="product.line.total" min="" max="" 
            step="product.stepCount" oninput="some condition"
            ng-change="oc.function1()" />
    <input  type="number"  ng-if="condition 2" ng-model="product.line.total" min="" max=""
            step="product.stepCount" oninput="some condition"
            ng-change="oc.function2()" />

    <input type="button" value="+" class="plus"
           ng-click="product.line.total = product.line.total + product.stepCount">

</div>

I have two input box above, based on ng-if condition either one will be shown at a time. Each ng-change is calling different function inside current controller. If I put separate controller then on click of +/- button following function is firing. But I want to call function inside ng-change

$scope.$watch('Count', function (oldValue, newValue) {
    if (newValue != oldValue)
      console.log(oldValue, newValue);
});

Solution

  • The code should avoid using the onchange attribute with the ng-model directive. The ng-if directive uses alot of resources. If the only reason it is being used is to switch the ng-change function, it should be avoided. The choice of ng-change function can be made in the controller.

    <div class="input-group" ng-repeat="product in oc.itemdetail.lines">
        <input type="button" value="-" class="minus"
               ng-click="oc.decrement(product)">
    
        <input  type="number"  ng-model="product.line.total" min="" max="" 
                step="product.stepCount" ng-change="oc.update(product)" />
    
        <input type="button" value="+" class="plus"
               ng-click="oc.increment(product)">
    
    </div>
    

    Avoid complex formulations in templates. Instead put them in the controller:

    oc.update = function(product) {
       if (oc.<condition 1>) {
         oc.function1();
       };
       if (oc.<condition 2>) {
         oc.function2();
       };
    };
    

    For performance reasons, avoid using watchers. Instead use the functions that change the model to invoke update operations:

    oc.decrement = function(product) {
        product.line.total = product.line.total - product.stepCount;
        oc.update(product);
    };
    
    oc.increment = function(product) {
        product.line.total = product.line.total + product.stepCount;
        oc.update(product);
    };
    

    Putting complex expressions in the controller makes the code easier to understand, debug, test, and maintain.