1

I would like to execute a function any time that values in a form (or accompanying model) are changed in AngularJS 1.6. I've tried a few things, including $scope.$watch, but it seems this method isn't available in 1.6.

Other than putting an ng-change attribute on each form element, what can I do? Tried putting this on the form too, but AngularJS complains that there is no ng-model.

georgeawg
  • 48,608
  • 13
  • 72
  • 95
serlingpa
  • 12,024
  • 24
  • 80
  • 130
  • http://stackoverflow.com/questions/35534479/angularjs-1-5-component-does-not-support-watchers-what-is-the-work-around – Sajeetharan Feb 06 '17 at 13:38

4 Answers4

0

Please try to use object notations in your ng-model please refer the following code and plunker link. It may help you.

in your html:

    <form name="details">
    <div>
      <input type="text" ng-model="formDetails.firstName" />
    </div>
    <div>
      <input type="text" ng-model="formDetails.secondName" />
    </div>
    <div>
      <button ng-click="fnSubmit()">Submit</button>
    </div>
  </form>

in your controller:

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.formDetails={}
  $scope.fnSubmit=function(){
    console.log($scope.formDetails);
  }
});

What ever may be the version it will work fine. We can avoid using ng-change for each input field in your form.

Please find the plunker link

Ravi Teja Kumar Isetty
  • 1,559
  • 4
  • 21
  • 39
0

I could think of creating a custom directive for this:

yourModule.directive("formChanged", function ($parse) {
return {
    restrict: 'A',
    link: function (scope, element, attrs) {

        var handler = $parse(attrs.formChanged);

        element.find('[ng-model]').each(function () {
            $(this).on('change', function () {
                handler(scope)();
            });
        });
    }
  }
});

Then you can use this on your form or any other HTML element like this:

<form form-changed="yourChangeCallback">
   <input type="text" ng-model="model.example"/>
</form>

Now the directive actually will just set an onchange event on every element that has the ngModel directive.

Eddi
  • 782
  • 1
  • 7
  • 20
  • Pretty elegant, but I can imagine that not always the `ng-model` is attached to input fields, for example with custom directives/3rd party directives. I think you can just bind the `change` event to the form instead – devqon Feb 06 '17 at 14:12
  • Well, I did not think of that case but actually I never used a 3rd party that added the `ngModel` directive itself. However, the whole solution is a pretty static approach and requires all the input elements to be already there when evaluated. The directive still could be improved. – Eddi Feb 06 '17 at 14:22
0

You can create a directive that listens to some events of the form:

.directive("formOnChange", function($parse){
    return {
        require: "form",
        link: function(scope, element, attrs){
            var cb = $parse(attrs.formOnChange);
            element.on("change keyup", function(){
                cb(scope);
            });
        }
    }
});

And usage:

<form name="myForm"
      form-on-change="doSomething()">
devqon
  • 13,818
  • 2
  • 30
  • 45
0

One idea is to create an ng-model directive that reports changes to a service.

app.directive("ngModel", function(changeService) {
    return {
        require: "ngModel",
        link: function(scope, elem, attrs, ngModel) {
            ngModel.$viewChangeListeners.push(
                function () {
                    changeService.report(ngModel.$viewValue, elem, attrs);
                } 
            );
        })
    };
});

The above example adds a $viewChangeListener to each ngModelController which reports changes to a service. The $viewChangeListeners array is the same hook that the ng-change directive uses.

Example of a service:

app.service("changeService", function() {
    this.report = function(value, elem, attrs) {
        var name = attrs.name || attrs.ngModel; 
        console.log(name + " changed to " + value);
    };
});

The DEMO in PLNKR.

georgeawg
  • 48,608
  • 13
  • 72
  • 95