ngChange-like functionality for the entire form

允我心安 提交于 2019-11-27 19:17:44

There isn't a built-in way to do ng-change for a form.

It may not even be needed, because if you organized your view model properly, then your form inputs are likely bound to a certain scope-exposed property:

$scope.formData = {};

and in the View:

<form name="form1">
  <input ng-model="formData.a">
  <input ng-model="formData.b">
</form>

Then you could deep-watch (with $watch) for model changes (and apply whatever debounce option on elements that you need):

$scope.$watch("formData", function(){
  console.log("something has changed");
}, true);

Then problem is, of course, that this is a deep-watch and it is expensive. Also, it reacts not only to changes in the Form, but also to a change in formData from any source.

So, as an alternative, you could create your own directive to compliment the form and react to form's change events.

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

and the usage is:

<form name="form1" form-on-change="doSomething()">
  <input ng-model="formData.a">
  <input ng-model="formData.b">
</form>

plunker for illustration.

Note, that the "change" event is fired only on blur for a text input, as per jQuery documentation:

The change event is sent to an element when its value changes. This event is limited to <input> elements, <textarea> boxes and <select> elements. For select boxes, checkboxes, and radio buttons, the event is fired immediately when the user makes a selection with the mouse, but for the other element types the event is deferred until the element loses focus.

Dayan Moreno Leon

one "hacky" way to do this is by setting a watcher to the form dirty, valid depending on your requirements you can do something like

   $scope.$watch('form.$dirty',function(v){
         if(!v){return}
         form.$setPristine()
         /*do something here*/
    })

this will execute everytime the form gets modified, if you only want to execute your code on valid modified form you can do

       if(!v || form.$invalid){return}

and if you only want to execute your code when the form steps to $valid state just need to set up your watcher for 'form.$valid'

if you don't like to pollute your scope with watchers, you can always create a directive around the form that exposes a on-change api event and internally takes care of the watcher

As per Eric Soyke comment you could hook up the check of the form change on the keyup event.

This way you could simply use the builtin directive ng-keyup:

<form name="form1" ng-keyup="doSomething()">

okay, super super late answer ... but this works pretty neat

// html
<form name="$ctrl.form">...</form>

// controller
function $postLink() {
    ctrl.form.$$element.on('change', function () {
        console.log('fired');
    });
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!