1

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);
});
subha
  • 1,050
  • 2
  • 15
  • 42
  • Read [What are the nuances of scope prototypal / prototypical inheritance in AngularJS?](https://stackoverflow.com/a/14049482/5535245). New AngularJS developers often do not realize that `ng-repeat`, `ng-switch`, `ng-view`, `ng-include` and `ng-if` all create new child scopes, so the problem often shows up when these directives are involved. The data hiding issue with primitives can be easily avoided by following the "best practice" of always have a '.' in your ng-models. – georgeawg Oct 09 '19 at 19:05
  • @georgeawg Actually for simplicity I gave sample binding object. My ng-model actually binds with object. Please check my updated question – subha Oct 09 '19 at 19:17
  • 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. – georgeawg Oct 09 '19 at 20:11
  • Could you please share some example that shows ng-change in controller??. ng-if is used only to change function in ng-change – subha Oct 09 '19 at 21:05

2 Answers2

1

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.

georgeawg
  • 48,608
  • 13
  • 72
  • 95
  • If you could please share some link that show's best coding practices in angular. Thanks...this is working great with neat code. – subha Oct 10 '19 at 13:32
0

You can try by moving this 'Count = Count + s.increment' code on the ng-click event into a function in the JS file and in that function you can call ct.function2().

eg:-

   $ct.Counter = function(){
      Count = Count + s.increment;
       ct.function2();
   }

and call this method on ng-click

    ng-click="ct.Counter()"

Similarly you can implement the minus scenario.

Harry Manoharan
  • 181
  • 1
  • 12