how to set all inputs as $touched without submit button AngularJS
Solution 1
You could follow a format similar to this:
if ($scope.form.$invalid) {
angular.forEach($scope.form.$error, function (field) {
angular.forEach(field, function(errorField){
errorField.$setTouched();
});
});
}
See '$setTouched': https://docs.angularjs.org/api/ng/type/ngModel.NgModelController
Solution 2
For nested forms:
function setFormTouched(form) {
// Check if the form/property has the $setSubmitted method
if (form.hasOwnProperty('$submitted')) {
// Iterate through each of the required error properties
angular.forEach(form.$error, function (errorType) {
// Iterate through each error type
angular.forEach(errorType, function (prop) {
// Check if the property has the $setTouched method
if (prop.hasOwnProperty('$touched')) prop.$setTouched();
// Recursive call to handle nested forms
setFormTouched(prop);
});
});
}
}
Solution is based on codepen by Patrick Marabeas But I had to edit the original code because hasOwnProperty
didn't work for functions defined in prototype.
For example:
if(prop.hasOwnProperty('$setTouched'))
Always returned false.
EDIT: What I originally needed was a way to make it easier for the user to find errors in nested tabs. This was the final working scope function used for disabling/enabling submit button and error message:
$scope.isFormValid = function (topLevelForm) {
if (topLevelForm.$valid) {
return true;
}
// Form not valid, triggering fields to make it easier to find errors
setFormTouched(topLevelForm);
function setFormTouched(form) {
// Check if the form/property has the $setSubmitted method
if (form.hasOwnProperty('$submitted')) {
// Iterate through each of the required error properties
angular.forEach(form.$error, function (errorType) {
// Iterate through each error type
angular.forEach(errorType, function (prop) {
// Check if the property has the $setTouched method
if (prop.hasOwnProperty('$touched')) prop.$setTouched();
// Recursive call to handle nested forms
setFormTouched(prop);
});
});
}
}
return false;
};
yl2015
Updated on June 14, 2022Comments
-
yl2015 almost 2 years
I have a directive that validates inputs inside a form based on their
$valid
and$untouched
properties - if the input was "touched" it checks for validation and colors the font and border in red/green accordingly, if the input wasn't "touched" it won't do anything.I'm using ngBootBox's custom dialog so i don't have the
type="submit"
kind of button for submitting the form, I'm using the callback function of the "Create" button in order to pass/save the data.My problem is that when I click the "create" button and the form is not "valid" because some of the fields are empty - my inputs are still "untouched" so the
$watch
function isn't being called. Any solutions? Is there a way to do something like this:$scope.createProjectForm.$setTouched(true);
that will make all child inputs of that form to get that value?I also tried that and it didn't work:
angular.forEach($scope.createProjectForm, function(field){ field.$setTouched(true); });
this is my validation directive:
angular.module('mean.theme').directive("inputValidation", function () { return { restrict: 'EA', require: 'ngModel', link: function (scope, inputElement, attrs, ngModelCtrl) { var $icon = $('<i class="fa"></i>'); inputElement.before($icon); scope.$watchGroup([ function(){ return ngModelCtrl.$untouched; }, function(){ return ngModelCtrl.$valid; } ], function(Paramaters){ console.log(scope); if(!Paramaters[0]) { if (Paramaters[1]) { inputElement.switchClass('validation-warning-border','validation-success-border',50) inputElement.prev().switchClass('fa-warning validation-warning-font' , 'fa-check validation-success-font',50); } else { inputElement.switchClass('validation-success-border','validation-warning-border',50) inputElement.prev().switchClass('fa-check validation-success-font','fa-warning validation-warning-font',50) } } }); } }; });
and this is part of my controller code:
$scope.create = function () { var options = { title: 'Create', templateUrl: 'project.html', scope: $scope, buttons: { warning: { label: "Cancel", className: "btn-link", callback: function () { } }, success: { label: "Create", className: "green", callback: function () { if ($scope.createProjectForm.$valid){ $scope.createProject(template); } else { $scope.project.createButtonClicked = true; return false; } } } } }; $ngBootbox.customDialog(options); };
and this is part of my HTML code:
<form role="form" name="createProjectForm"> <label> Name Your Project </label> <div> <input type="text" name="project.name" ng-model="project.name" required="required" class="form control" input-validation/> </div> <label> Name Your Project </label> <div> <input type="text" name="project.title" ng-model="project.title" required="required" class="form control" input-validation/> </div> </form>
- EDIT:
I found what i needed, easier and shorter way to do it:
It is possible to set manually:
$scope.createProjectForm.$setSubmitted()
totrue
and then make the children(inputs)
$watch
for this change as well:scope.$watchGroup([ function(){ return ngModelCtrl.$untouched; }, function(){ return ngModelCtrl.$valid; }, function(){ return ngModelCtrl.$$parentForm.$submitted; } ], function(Paramaters){ // code here }