I'm looking for a way to override ng-submit so that it performs some functions before evaluating/running the expression it contains. For example, I would like to do the following.
1) Set all fields dirty (or perhaps touched) so that all fields are validated even if the user has skipped over them.
2) Check that all fields validate. If not then don't continue.
3) If any fields are invalid then scroll the first invalid field and focus it.
I have found a few directives that do some of this, some create new element directives but none actually override/extend ngSubmit so I'm wondering if this is possible?
First, an element need not be "touched" for validation to work (that's about point #1). For example, this would invalidate the input, given $scope.test = "abcd";
and:
<input ng-model="test" ng-maxlength="3">
Second, #2 is easily achieved with form.$valid
:
<form name="form1" ng-submit="form1.$valid && onSubmit()">
...
</form>
If pre-submit logic is more complicated then this, it could/should be done in the controller, for example, in the onSubmit()
function.
But, if your pre-submit logic is View-related (as opposed to ViewModel-related) - and scrolling is View-related - then you could create another ngSubmit
directive with higher priority and prevent default submit event handling:
.directive("ngSubmit", function() {
return {
require: "?form",
priority: 10,
link: {
pre: function(scope, element, attrs, form) {
element.on("submit", function(event) {
if (form && !form.$valid) {
event.stopImmediatePropagation();
event.preventDefault();
// do whatever you need to scroll here
}
})
}
}
}
});
EDIT:
Using pre
-link is important here due to order of link function executions. The order of execution is:
1. pre-link of parent or higher priority directive
2. pre-link of child or lower priority directive
3. post-link of child or lower priority directive
4. post-link of parent or higher priority directive
So, the use of higher priority and pre
-link ensures that this directive registers element.on("submit", ...)
before the built-in ngSubmit
does it, so it can have a first go at event handling.
This code should get you started as it addresses criterias number 1, 2 and gives you a hook for number 3.
As for scrolling to the invalid fields, I have not tried/needed that yet but sounds interesting. I guess you can get real bored and create an entire "form wrapper directive", though seems like overkill..
I would just use a service method that can be called in my controller. Are you thinking of just scrolling to the first invalid field and focusing it?
Template
<!-- Form Template -->
<form name="form" novalidate ng-submit="vm.submit(form.$valid, vm.data)">
<input type="text"
name="blah"
ng-model="vm.data.blah"
ng-model-options="{debounce: {'default': 300, blur: 0}}"
required
formnovalidate/>
<div ng-messages="form.blah.$error"
ng-messages-include="messages.html"
ng-if="form.$submitted || form.blah.$touched">
</div>
<button type="submit">Submit</button>
</form>
<!-- messages.html -->
<div ng-message="required">This field is required</div>
Controller
vm.data = {};
vm.submit = function(isValid, data) {
if (!isValid) {
//Scroll to bad field
return;
}
// Do form submission via service
};
来源:https://stackoverflow.com/questions/30425605/is-it-possible-to-override-ng-submit