问题
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.
回答1:
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.
回答2:
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
回答3:
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()">
回答4:
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');
});
}
来源:https://stackoverflow.com/questions/28677638/ngchange-like-functionality-for-the-entire-form