Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ngChange-like functionality for the entire form

I would like to do an equivalent of ng-change for the entire form whenever there is a change in one of its input fields.

I know that since AngularJS 1.3 I have the debounce option but it applies only for a single input.

I'm looking for a "debounce"/"on change" functionality that will apply for the entire form.

like image 760
chenop Avatar asked Feb 23 '15 15:02

chenop


People also ask

What is forms in AngularJS?

Forms in AngularJS provides data-binding and validation of input controls.

What is ng-model and ng-change?

Ng-change is a directive in AngularJS which is meant for performing operations when a component value or event is changed. In other words, ng-change directive tells AngularJS what to do when the value of an HTML element changes. An ng-model directive is required by the ng-change directive.

How to use ng-change in AngularJS?

The ng-change Directive in AngularJS is used whenever the value of an input element changes. The expression is evaluated immediately whenever there is a change in the input value. It requires an ng-model directive to be present. It is triggered whenever there is any single change in the input.

Why we use ng on change in Angular?

AngularJS ng-change DirectiveThe ng-change event is triggered at every change in the value. It will not wait until all changes are made, or when the input field loses focus. The ng-change event is only triggered if there is a actual change in the input value, and not if the change was made from a JavaScript.


4 Answers

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.

like image 198
New Dev Avatar answered Nov 04 '22 10:11

New Dev


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

like image 22
Dayan Moreno Leon Avatar answered Nov 04 '22 11:11

Dayan Moreno Leon


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()">
like image 27
Lorenzo Meriggi Avatar answered Nov 04 '22 11:11

Lorenzo Meriggi


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');
    });
}
like image 2
Eydrian Avatar answered Nov 04 '22 12:11

Eydrian