I have a form which need to show validation error messages if clicked submit.
Here is a working plunker
<form name="frmRegister" ng-submit="register();" novalidate>
<div>
<input placeholder="First Name" name="first_name" type="text" ng-model="user.firstName" required />
<span ng-show="frmRegister.first_name.$dirty && frmRegister.first_name.$error.required">First Name is required</span>
</div>
<div>
<input placeholder="Last Name" name="last_name" type="text" ng-model="user.lastName" required />
<span ng-show="frmRegister.last_name.$dirty && frmRegister.last_name.$error.required">Last Name is required</span>
</div>
<div>
<input placeholder="Email" name="email" type="email" ng-model="user.email" required />
<span ng-show="frmRegister.email.$dirty && frmRegister.email.$error.required">Email is required.</span>
<span ng-show="frmRegister.email.$dirty && frmRegister.email.$error.email">Invalid Email address.</span>
</div>
<input type="submit" value="Save" />
<span ng-show="registered">YOU ARE NOW REGISTERED USER</span>
</form>
Validation works normally when user start making changes. But it doesn't show any error messages If clicked submit without entering anything.
Any thought of achieving this?. Or in other way how can I make each input field $dirty when clicks the Submit button
I found this fiddle http://jsfiddle.net/thomporter/ANxmv/2/ which does a nifty trick to cause control validation.
Basically it declares a scope member submitted and sets it true when you click submit. The model error binding use this extra expression to show the error message like
submitted && form.email.$error.required
UPDATE
As pointed out in #Hafez's comment (give him some upvotes!), the Angular 1.3+ solution is simply:
form.$submitted && form.email.$error.required
Since I'm using Bootstrap 3, I use a directive:
(see plunkr)
var ValidSubmit = ['$parse', function ($parse) {
return {
compile: function compile(tElement, tAttrs, transclude) {
return {
post: function postLink(scope, element, iAttrs, controller) {
var form = element.controller('form');
form.$submitted = false;
var fn = $parse(iAttrs.validSubmit);
element.on('submit', function(event) {
scope.$apply(function() {
element.addClass('ng-submitted');
form.$submitted = true;
if(form.$valid) {
fn(scope, {$event:event});
}
});
});
scope.$watch(function() { return form.$valid}, function(isValid) {
if(form.$submitted == false) return;
if(isValid) {
element.removeClass('has-error').addClass('has-success');
} else {
element.removeClass('has-success');
element.addClass('has-error');
}
});
}
}
}
}
}]
app.directive('validSubmit', ValidSubmit);
and then in my HTML:
<form class="form-horizontal" role="form" name="form" novalidate valid-submit="connect()">
<div class="form-group">
<div class="input-group col col-sm-11 col-sm-offset-1">
<span class="input-group-addon input-large"><i class="glyphicon glyphicon-envelope"></i></span>
<input class="input-large form-control" type="email" id="email" placeholder="Email" name="email" ng-model="email" required="required">
</div>
<p class="col-sm-offset-3 help-block error" ng-show="form.$submitted && form.email.$error.required">please enter your email</p>
<p class="col-sm-offset-3 help-block error" ng-show="form.$submitted && form.email.$error.email">please enter a valid email</p>
</div>
</form>
UPDATED
In my latest project, I use Ionic so I have the following, which automatically puts .valid or .invalid on the input-item's:
.directive('input', ['$timeout', function ($timeout) {
function findParent(element, selector) {
selector = selector || 'item';
var parent = element.parent();
while (parent && parent.length) {
parent = angular.element(parent);
if (parent.hasClass(selector)) {
break;
}
parent = parent && parent.parent && parent.parent();
}
return parent;
}
return {
restrict: 'E',
require: ['?^ngModel', '^form'],
priority: 1,
link: function (scope, element, attrs, ctrls) {
var ngModelCtrl = ctrls[0];
var form = ctrls[1];
if (!ngModelCtrl || form.$name !== 'form' || attrs.type === 'radio' || attrs.type === 'checkbox') {
return;
}
function setValidClass() {
var parent = findParent(element);
if (parent && parent.toggleClass) {
parent.addClass('validated');
parent.toggleClass('valid', ngModelCtrl.$valid && (ngModelCtrl.$dirty || form.$submitted));
parent.toggleClass('invalid', ngModelCtrl.$invalid && (ngModelCtrl.$dirty || form.$submitted));
$timeout(angular.noop);
}
}
scope.$watch(function () {
return form.$submitted;
}, function (b, a) {
setValidClass();
});
var before = void 0;
var update = function () {
before = element.val().trim();
ngModelCtrl.$setViewValue(before);
ngModelCtrl.$render();
setValidClass();
};
element
.on('focus', function (e) {
if (ngModelCtrl.$pristine) {
element.removeClass('$blurred');
}
})
.on('blur', function (e) {
if (ngModelCtrl.$dirty) {
setValidClass();
element.addClass('$blurred');
}
}).on('change', function (e) {
if (form.$submitted || element.hasClass('$blurred')) {
setValidClass();
}
}).on('paste', function (e) {
if (form.$submitted || element.hasClass('$blurred')) {
setValidClass();
}
})
;
}
};
}])
and then in the HTML:
<form name='form' novalidate="novalidate" ng-submit="auth.signin(form, vm)">
<label class="item item-input item-floating-label">
<span class="input-label">Email</span>
<input type="email" placeholder="Email" ng-model="vm.email" autofocus="true" required
>
</label>
<button ng-if="!posting" type="submit" class="item button-block item-balanced item-icon-right call-to-action">Login<i class="icon ion-chevron-right"></i>
</button>
and in the controller:
self.signin = function (form, data) {
if (!form.$valid) return;
Authentication.emailLogin(data)
//...
so, now, in the CSS, you can do stuff like:
.item.valid::before{
float: right;
font-family: "Ionicons";
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
text-rendering: auto;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #66cc33;
margin-right: 8px;
font-size: 24px;
content: "\f122";
}
.item.invalid::before{
float: right;
font-family: "Ionicons";
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
text-rendering: auto;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #ef4e3a;
margin-right: 8px;
font-size: 24px;
content: "\f12a";
/*
border-left: solid 2px #ef4e3a !important;
border-right: solid 2px #ef4e3a !important;
*/
}
MUCH SIMPLER!
I also had the same issue, I solved the problem by adding a ng-submit which sets the variable submitted to true.
<form name="form" ng-submit="submitted = true" novalidate>
<div>
<span ng-if="submitted && form.email.$error.email">invalid email address</span>
<span ng-if="submitted && form.email.$error.required">required</span>
<label>email</label>
<input type="email" name="email" ng-model="user.email" required>
</div>
<div>
<span ng-if="submitted && form.name.$error.required">required</span>
<label>name</label>
<input type="text" name="name" ng-model="user.name" required>
</div>
<button ng-click="form.$valid && save(user)">Save</button>
</form>
I like the idea of using $submitted, I think I've to upgrade Angular to 1.3 ;)
I can come up with 2 ways to achieve it.
The first one is to remove novalidate to enable the browser's validation.
Second, you can disable the save button when the form is not valid like this
<input ng-disabled="!frmRegister.$valid" type="submit" value="Save" />
Hope it helps.
There are two simple & elegant ways to do it.
Pure CSS:
After first form submission, despite the form validity, Angular will add a ng-submitted class to all form elements inside the form just submitted.
We can use .ng-submitted to controller our element via CSS.
if you want to display an error text only when user have submitted e.g.
.error { display: none }
.ng-submitted .error {
display: block;
}
Using a value from Scope:
After first form submission, despite the form validity, Angular will set [your form name].$submitted to true. Thus, we can use that value to control elements.
<div ng-show="yourFormName.$submitted">error message</div>
<form name="yourFormName"></form>
My solution with bootstrap 3
http://jsfiddle.net/rimian/epxrbzn9/
<form class="form" name="form" ng-app novalidate>
<div class="form-group">
<input name="first_name"
type="text"
class="form-control"
ng-model="first_name"
placeholder="First Name"
required />
</div>
<div class="form-group">
<input name="last_name"
type="text"
class="form-control"
ng-model="last_name"
placeholder="Last Name"
required />
</div>
<button
type="submit"
class="btn btn-primary btn-large"
ng-click="submitted=true">
Submit
</button>
<div ng-show="submitted && form.$invalid" class="alert alert-danger">
<div ng-show="form.first_name.$error.required">
First Name is Required
</div>
<div ng-show="form.last_name.$error.required">
Last Name is Required
</div>
</div>
</form>
You only need to check if the form is dirty and valid before submitting it. Checkout the following code.
<form name="frmRegister" data-ng-submit="frmRegister.$valid && frmRegister.$dirty ? register() : return false;" novalidate>
And also you can disable your submit button with the following change:
<input type="submit" value="Save" data-ng-disable="frmRegister.$invalid || !frmRegister.$dirty" />
This should help for your initial
http://jsfiddle.net/LRD5x/30/ A simple solution.
HTML
<form ng-submit="sendForm($event)" ng-class={submitted:submitted}>
JS
$scope.sendForm = function($event) {
$event.preventDefault()
$scope.submitted = true
};
CSS
.submitted input.ng-invalid:not(:focus) {
background-color: #FA787E;
}
input.ng-invalid ~ .alert{
display:none;
}
.submitted input.ng-invalid ~ .alert{
display:block;
}
I like the solution from realcrowd the best.
HTML:
<form role="form" id="form" name="form" autocomplete="off" novalidate rc-submit="signup()">
<div class="form-group" ng-class="{'has-error': rc.form.hasError(form.firstName)}">
<label for="firstName">Your First Name</label>
<input type="text" id="firstName" name="firstName" class="form-control input-sm" placeholder="First Name" ng-maxlength="40" required="required" ng-model="owner.name.first"/>
<div class="help-block" ng-show="rc.form.hasError(form.firstName)">{{rc.form.getErrMsg(form.firstName)}}</div>
</div>
</form>
javascript:
//define custom submit directive
var rcSubmitDirective = {
'rcSubmit': ['$parse', function ($parse) {
return {
restrict: 'A',
require: ['rcSubmit', '?form'],
controller: ['$scope', function ($scope) {
this.attempted = false;
var formController = null;
this.setAttempted = function() {
this.attempted = true;
};
this.setFormController = function(controller) {
formController = controller;
};
this.hasError = function (fieldModelController) {
if (!formController) return false;
if (fieldModelController) {
return fieldModelController.$invalid && this.attempted;
} else {
return formController && formController.$invalid && this.attempted;
}
};
this.getErrMsg=function(ctrl){
var e=ctrl.$error;
var errMsg;
if (e.required){
errMsg='Please enter a value';
}
return errMsg;
}
}],
compile: function(cElement, cAttributes, transclude) {
return {
pre: function(scope, formElement, attributes, controllers) {
var submitController = controllers[0];
var formController = (controllers.length > 1) ? controllers[1] : null;
submitController.setFormController(formController);
scope.rc = scope.rc || {};
scope.rc[attributes.name] = submitController;
},
post: function(scope, formElement, attributes, controllers) {
var submitController = controllers[0];
var formController = (controllers.length > 1) ? controllers[1] : null;
var fn = $parse(attributes.rcSubmit);
formElement.bind('submit', function (event) {
submitController.setAttempted();
if (!scope.$$phase) scope.$apply();
if (!formController.$valid) return false;
scope.$apply(function() {
fn(scope, {$event:event});
});
});
}
};
}
};
}]
};
app.directive(rcSubmitDirective);
A complete solution to the validate form with angularjs.
HTML is as follows.
<div ng-app="areaApp" ng-controller="addCtrler">
<form class="form-horizontal" name="fareainfo">
<div class="form-group">
<label for="input-areaname" class="col-sm-2 control-label">Area Name : </label>
<div class="col-sm-4">
<input type="text" class="form-control" name="name" id="input-areaname" ng-model="Area.Name" placeholder="" required>
<span class="text-danger" ng-show="(fareainfo.$submitted || fareainfo.name.$dirty) && fareainfo.name.$error.required"> Field is required</span>
</div>
</div>
<div class="col-sm-12">
<button type="button" class="btn btn-primary pull-right" ng-click="submitAreaInfo()">Submit</button>
</div>
</form>
</div>
AngularJS App and Controller is as follows
var areaApp = angular.module('areaApp', []);
areaApp.controller('addCtrler', function ($scope) {
$scope.submitAreaInfo = function () {
if ($scope.fareainfo.$valid) {
//after Form is Valid
} else {
$scope.fareainfo.$setSubmitted();
}
};
});
Important Code Segments
ng-app="areaApp" ng-controller="addCtrler"
Defines the angular app and controller
ng-show="(fareainfo.$submitted || fareainfo.name.$dirty) && fareainfo.name.$error.required"
Above condition ensure that whenever a user first sees the form there's no any validation error on the screen and after a user does changes to the form it ensure that validation message show on the screen. .name. is the name attribute of the input element.
$scope.fareainfo.$valid
Above code, segment check whether the form is valid whenever a user submits the form.
$scope.fareainfo.$setSubmitted();
Above code, segment ensures that all validation messages are displayed on the screen whenever a user submits the form without doing anything.
// This worked for me.
<form name="myForm" class="css-form" novalidate ng-submit="Save(myForm.$invalid)">
<input type="text" name="uName" ng-model="User.Name" required/>
<span ng-show="User.submitted && myForm.uName.$error.required">Name is required.</span>
<input ng-click="User.submitted=true" ng-disabled="User.submitted && tForm.$invalid" type="submit" value="Save" />
</form>
// in controller
$scope.Save(invalid)
{
if(invalid) return;
// save form
}
G45,
I faced same issue , i have created one directive , please check below hope it may be helpful
Directive :
app.directive('formSubmitValidation', function () {
return {
require: 'form',
compile: function (tElem, tAttr) {
tElem.data('augmented', true);
return function (scope, elem, attr, form) {
elem.on('submit', function ($event) {
scope.$broadcast('form:submit', form);
if (!form.$valid) {
$event.preventDefault();
}
scope.$apply(function () {
scope.submitted = true;
});
});
}
}
};
})
HTML :
<form name="loginForm" class="c-form-login" action="" method="POST" novalidate="novalidate" form-submit-validation="">
<div class="form-group">
<input type="email" class="form-control c-square c-theme input-lg" placeholder="Email" ng-model="_username" name="_username" required>
<span class="glyphicon glyphicon-user form-control-feedback c-font-grey"></span>
<span ng-show="submitted || loginForm._username.$dirty && loginForm._username.$invalid">
<span ng-show="loginForm._username.$invalid" class="error">Please enter a valid email.</span>
</span>
</div>
<button type="submit" class="pull-right btn btn-lg c-theme-btn c-btn-square c-btn-uppercase c-btn-bold">Login</button>
</form>
Try this code:
<INPUT TYPE="submit" VALUE="Save" onClick="validateTester()">
This funvtion will validate your result
function validateTester() {
var flag = true
var Tester = document.forms.Tester
if (Tester.line1.value!="JavaScript") {
alert("First box must say 'JavaScript'!")
flag = false
}
if (Tester.line2.value!="Kit") {
alert("Second box must say 'Kit'!")
flag = false
}
if (flag) {
alert("Form is valid! Submitting form...")
document.forms.Tester.submit()
}
}
Related
var app = angular.module('snc', []);
app.controller('contactForm', function($scope, $http) {
$scope.user = {};
$scope.submitForm = function() {
$http({
method: 'POST',
url: 'php-form/form.php',
data: $scope.user,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.success(function(data) {
console.log(data);
if (!data.success) {
if ($scope.errorName = data.errors.name) {
$(".alert-set").removeClass('alert-danger');
$(".alert-set").removeClass('alert-success');
$(".alert-set").fadeIn(1000);
$(".alert-set").removeClass("hide");
$(".alert-set").fadeOut(5000);
$(".alert-set").addClass('alert-warning');
$(".Message-txt").text(data.errors.name);
} else if ($scope.errorMobile = data.errors.mobile) {
$(".alert-set").removeClass('alert-danger');
$(".alert-set").removeClass('alert-success');
$(".alert-set").fadeIn(1000);
$(".alert-set").removeClass("hide");
$(".alert-set").fadeOut(5000);
$(".alert-set").addClass('alert-warning');
$(".Message-txt").text(data.errors.mobile);
} else if (data.errors.email == 'fail') {
$(".alert-set").removeClass('alert-danger');
$(".alert-set").removeClass('alert-success');
$(".alert-set").fadeIn(1000);
$(".alert-set").removeClass("hide");
$(".alert-set").fadeOut(5000);
$(".alert-set").addClass('alert-warning');
$(".Message-txt").text('Sorry, Failed to send E-mail.');
} else {
$(".alert-set").removeClass('alert-warning');
$(".alert-set").removeClass('alert-success');
$(".alert-set").fadeIn(1000);
$(".alert-set").removeClass("hide");
$(".alert-set").fadeOut(5000);
$(".alert-set").addClass('alert-dnager');
$(".Message-txt").text('somthing went wrong please try again.');
}
} else {
$(".alert-set").removeClass('alert-danger');
$(".alert-set").removeClass('alert-warning');
$(".alert-set").fadeIn(1000);
$(".alert-set").removeClass("hide");
$(".alert-set").fadeOut(5000);
$(".alert-set").addClass('alert-success');
$(".Message-txt").text(data.message);
this.submitForm = {};
}
});
};
});
<form name="queryForm" ng-submit="submitForm()" novalidate>
<div class="form-group">
<label for="Name">Name:<span class="text-danger">*</span></label>
<input type="text" class="form-control" ng-model="user.name" id="name" placeholder="Enter Your Name">
</div>
<div class="form-group">
<label for="Mobile">Mobile:<span class="text-danger">*</span></label>
<input type="number" class="form-control" ng-model="user.mobile" id="mobile" placeholder="Enter Your Mobile Number">
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="email" class="form-control" ng-model="user.email" id="email" placeholder="Enter Your Email">
</div>
<div class="form-group">
<label for="Message">Message:</label>
<textarea type="text" class="form-control" ng-model="user.message" id="name" placeholder="Enter Your Message" rows="4"></textarea>
</div>
<button type="submit" class="btn btn-snc">Submit</button>
<div class="alert alert-dismissible alert-set">
<strong class='Message-txt'></strong>
</div>
</form>
I have a simple contact form it has to send query data to php page and I want to disable button and change button text after submitting form and also full form reset after submit. I tried but I always get some type of angular error. Can you help me to solve it and if you are a Angular Developer then can you please check this form and let me know if I need to change something.
To reset the form, you could use something like:
(Mind: you've got two name ID. An ID should be UNIQ on your page).
function onSubmit()
{
$('#submit_button').text('Loading…');
resetForm();
}
function resetForm()
{
for(let id of ['name','mobile','email', 'message'])
{
$("#"+id).val('');
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form name="queryForm" ng-submit="submitForm()" novalidate>
<div class="form-group">
<label for="Name">Name:<span class="text-danger">*</span></label>
<input type="text" class="form-control" ng-model="user.name" id="name" placeholder="Enter Your Name">
</div>
<div class="form-group">
<label for="Mobile">Mobile:<span class="text-danger">*</span></label>
<input type="number" class="form-control" ng-model="user.mobile" id="mobile" placeholder="Enter Your Mobile Number">
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="email" class="form-control" ng-model="user.email" id="email" placeholder="Enter Your Email" value="some text">
</div>
<div class="form-group">
<label for="Message">Message:</label>
<textarea type="text" class="form-control" ng-model="user.message" id="message" placeholder="Enter Your Message" rows="4">Some text</textarea>
</div>
<button id="submit_button" type="button" class="btn btn-snc" onclick="onSubmit()">RESET FORM</button>
<div class="alert alert-dismissible alert-set">
<strong class='Message-txt'></strong>
</div>
</form>
An assignation is not a comparison:
$scope.errorName = data.errors.name ;
… is an assignation which means: put the data.errors.name into the $scope.errorName variable.
$scope.errorName == data.errors.name
… is a comparison which means: data.errors.name is equal to $scope.errorName.
If you use an assignation instead of a comparison, the result will always be true as long as the value is true-like.
So:
if ( a = 1 ) { /* always true */ }
if ( a == 1 ) { /* true only if `a` is equal to 1 */
if ( a === 1 ) { /* true only if `a` is strictly equal to 1 */
if ( a = "false" ) { /* always true (a string not empty is true) */ }
if ( a == "false" ) { /* true only if `a` is equal to "false" */
if ( a === "false" ) { /* true only if `a` is strictly equal to "false" */
The strictly above means of the same type. For instance:
1 == "1" // => true
1 === "1" // => not true. The Former is a Number, the latter is
// a String.
You should avoid the typo like:
$(".alert-set").addClass('alert-dnager');
To avoid it, try to keep your code as clean as possible. You'll be able to avoid a lot of errors, you'll have a better understanding of your code, and other people can help you more efficiency.
Your if error statement could become:
.success(function(data) {
console.log(data);
if ( false === data.success) {
// Typo error avoiding: NOT plain-text USE variables
let alertClass = '.alert-set';
let errMessage = '' ;
// Reduce the amount of code
$(alertClass)
.addClass('alert-warning')
.removeClass('alert-success')
.fadeIn(1000)
.removeClass("hide")
.fadeOut(5000)
.removeClass('alert-danger') ;
// Treat only what you have to treat
// You could use a lambda function, too:
// let errMessage = function(val){ return ... }(actual value);
if ( $scope.errorName == data.errors.name )
{
errMessage = data.errors.name ;
}
else if ( $scope.errorMobile == data.errors.mobile )
{
errMessage = data.errors.mobile ;
}
else if (data.errors.email == 'fail')
{
errMessage = 'Sorry, Failed to send E-mail.';
}
else {
errMessage = 'somthing went wrong please try again.' ;
}
// Only one action
$(".Message-txt").text(errMessage) ;
Now we can work ;-).
Keep in mind that we don't want to help you if your code is not clean and if we can't understand at a first glance what's going on.
when clicked on submit button, it will call function, in that function i am trying to write logic to disable submit button when fields are not valid, here email must be contain #, dot and after dot minimum 2 & maximum 4 alphabet characters. I tried bellow code.
HTML:
<div ng-app="myApp" ng-controller="myCtrl">
<form name="myForm">
<div>
<select id="country" style="width:250px;" class="" name="selectFranchise" ng-model="state1" ng-change="displayState(state1)"
ng-required>
<option ng-repeat="(key,country) in countries" value="{{key}}">{{country[0]}}</option>
</select>
</div>
<div>
<select id="state" ng-disabled="!states[state1].length" ng-model="cities" ng-required>
<option ng-repeat="(state,city) in states[state1]" value="{{city}}">{{city}}</option>
</select>
</div>
<input type="email" ng-disable="myForm.user.email.$valid" ng-model="user.email" name="eamil" ng-required/>
<button ng-disable="myForm.user.email.$valid" ng-click="formsubmit();">submit</button>
</form>
</div>
SCRIPT:
var app = angular.module('myApp', []);
app.controller('myCtrl', function ($scope) {
$scope.formsubmit = function () {
}
$scope.states = {
"IN": [
"Delhi",
"Goa",
"Gujarat",
"Himachal Pradesh",
]
};
$scope.countries = {
IN: ["India"],
ZA: ["South Africa"],
AT: ["Austria"]
}
$scope.state1 = Object.keys($scope.countries)[0];
$scope.lastName = "Doe";
});
jsfiddle
<form role="form" name="signupForm" ng-submit="signup()" novalidate>
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-6">
<div class="clearfix"> </div>
<div class="inputGroup">
<input type="text" id="su_username" name="username" class="form-control input-md"
ng-model="user.username" ng-minlength="8" required>
<span class="inputBar"></span>
<label translate="signup.form.username">Username</label>
<span class="text-danger" ng-show="signupForm.username.$dirty && signupForm.username.$invalid">
<span ng-show="signupForm.username.$error.required" translate="signup.messages.validate.username.required">Username is required.</span>
<span ng-show="signupForm.username.$error.minlength" translate="signup.messages.validate.username.minlength">Username must be at least 8 characters.</span>
</span>
</div>
</div>
<div class="col-xs-12 col-sm-6 col-md-6">
<div class="clearfix"> </div>
<div class="inputGroup">
<input type="email" name="email" id="su_email" class="form-control input-md"
ng-model="user.email" required>
<span class="inputBar"></span>
<label translate="signup.form.email">Email Address</label>
<span class="text-danger" ng-show="signupForm.email.$dirty && signupForm.email.$invalid">
<span ng-show="signupForm.email.$error.required" translate="signup.messages.validate.email.required">Email is required.</span>
<span ng-show="signupForm.email.$error.email" translate="signup.messages.validate.email.invalid">Invalid email address.</span>
</span>
</div>
</div>
</div>
<button type="submit" class="btn btn-custom btn-lg btn-block"
ng-disabled="signupForm.$invalid ">
1st of all you need to give your form a name here its signupForm .
2nd from there you need to give your input fields names for example here they areusername and email.
Then you can use various angular validation directives to set validation constrains like require , length then you can check for validation error using signupForm.username.$invalid and check various error like signupForm.email.$error.email.
Finally if you want to check if the whole from is valid use signupForm.$invalid
and for number validation use
angular.module('test')
.directive('validNumber', function() {
return {
require: '?ngModel',
link: function(scope, element, attrs, ngModelCtrl) {
if(!ngModelCtrl) {
return;
}
ngModelCtrl.$parsers.push(function(val) {
if (angular.isUndefined(val)) {
val = '';
}
var clean = val.replace( /[^0-9\.]/g, '');
if (val !== clean) {
ngModelCtrl.$setViewValue(clean);
ngModelCtrl.$render();
}
return clean;
});
element.bind('keypress', function(event) {
if(event.keyCode === 32) {
event.preventDefault();
}
});
}
};
});
you can find github example from here
var app = angular.module('jsbin', []);
app.controller('DemoCtrl', function() {
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Angular JS</title>
</head>
<body ng-app="jsbin">
<div ng-controller="DemoCtrl as demo">
<form name="form" novalidate ng-submit="validate()">
<input type="email" name="email" ng-model="email" required />
<span class="help-inline" ng-show="submitted && form.email.$error.required">Required</span>
<span class="help-inline" ng-show="submitted && form.email.$error.email">Invalid email</span>
<button type="submit" class="btn btn-primary btn-large" ng-disabled="submitted && form.email.$error.required || submitted && form.email.$error.email" ng-click="submitted=true">Submit</button>
</form>
</div>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>
</body>
</html>
Check This Out.
In order to disable the submit button, you can do something like this:
<form name="myForm">
<input ...>
...
<button type="button" ng-disabled="myForm.$invalid" ng-click="formsubmit();">
Submit
</button>
</form>
Notice that I have put ng-disabled with a condition of myForm being invalid. So, instead of waiting for user to click the button, we are disabling the submit button upfront when form is invalid!
For Email validation, I would suggest you to go with <input type = "email"...> unless you have specific email validation requirements not handled by type = "email"
Here's the updated fiddle which disables the submit button until we put a valid email address.
Edit: Here's an example of how ng-pattern can be used to validate email for given rules (i.e. email must contain #, dot and after dot minimum 2 & maximum 4 alphabet characters)
<input type="text" ng-model="user.email" name="email" required
ng-pattern="/[a-zA-Z0-9_.]+\#[a-zA-Z0-9_]+\.[a-zA-Z]{2,4}$/"/>
Here's the updated fiddle
Also, regex101 for the email validation regex
I have recently started working on AngularJS 1.6.
I am trying to submit a form programmatically. The reason is I want to validate a few fields (required field validation). I have spent a lot of efforts (probably 3-4 hours) trying to make this work but none of the existing answers on stack overflow or AngularJS docs seems to be working for me today (strange), hence I am posting this as last resort.
Below is my html
<form method="post" id="loginform" name="loginform" ng-submit="loginUser()" novalidate>
<div>
{{message}}
</div>
<div>
<label>User Name</label>
<input type="text" id="txtUserName" ng-model="user.UserName" name="user.UserName" />
</div>
<div>
<label>Password</label>
<input type="text" id="txtPassword" ng-model="user.Password" name="user.Password" />
</div>
<div>
<input type="submit" id="btnLogin" title="Save" name="btnLogin" value="Login" />
</div>
</form>
My angular code
var demoApp = angular.module('demoApp', []);
demoApp.controller("homeController", ["$scope", "$timeout", function ($scope, $timeout) {
$scope.loginUser = function () {
var form = document.getElementById("loginform");
//var form = $scope.loginform; - tried this here...
//var form = $scope["#loginform"]; tried this
//var form = angular.element(event.target); - tried this...
// tried a lot of other combinations as well...
form.attr("method", "post");
form.attr("action", "Home/Index");
form.append("UserName", $scope.user.UserName);
form.append("Password", $scope.user.Password);
form.append("RememberMe", false);
form.submit();
};
}]);
I keep on getting error 'attr' is not a function.
All I need is submit a form using post method, with values. Just before that I am trying to intercept the submit call and check for validations.
I am open to try any other approach as well. Such as changing the input type from submit to button. Putting the input outside the form. I would be more than happy if validations and submit both can happen any which way. I just want it to post back the values after validating on the client side and then the server will take care of the redirect.
Note: I want the form to do a full postback so that I can get it to redirect to another form. (I know I could use Ajax, but some other day, may be!)
1st of all avoid doing var form = document.getElementById("loginform");. Instead of using form.submit you can use the following code. Do it the angular way cheers :D
$scope.loginUser = function () {
if($scope.loginform.$valid){
user.rememberme=false;
$http({
url: 'Home/Index',
method: "POST",
data: user
})
.then(function(response) {
// success
},
function(response) { // optional
// failed
});
}
};
this is a code to validation if validation not complate button is not enable
<form method="post" id="loginform" name="loginform" ng-submit="loginUser()" novalidate>
<div>
{{message}}
</div>
<div>
<label>User Name</label>
<input type="text" id="txtUserName" required ng-model="user.UserName" name="UserName" />
</div>
<div>
<label>Password</label>
<input type="text" id="txtPassword" ng-model="Password" name="user.Password"required />
</div>
<div>
<input type="submit" ng-disabled="myForm.UserName.$invalid || myForm.Password.$invalid" id="btnLogin" title="Save" name="btnLogin" value="Login" />
</div>
</form>
You should use $scope when trying to access the form, something like $scope.loginform. But......
Take a look at ng-messages. Heres an example using ng-messages with your form:
<form id="loginform" name="loginform" ng-submit="loginUser()">
<div>
{{message}}
</div>
<div>
<label>User Name</label>
<input type="text" id="txtUserName" ng-model="user.UserName" name="user.UserName" required/>
<div class="help-block" ng-messages="loginform.txtUserName.$error" ng-show="loginform.txtUserName.$touched">
<p ng-message="required">Username is required.</p>
</div>
</div>
<div>
<label>Password</label>
<input type="text" id="txtPassword" ng-model="user.Password" name="user.Password" required/>
<div class="help-block" ng-messages="loginform.txtPassword.$error" ng-show="loginform.txtPassword.$touched">
<p ng-message="required">Password is required.</p>
</div>
</div>
<div>
<input type="submit" id="btnLogin" title="Save" name="btnLogin" value="Login" ng-click="loginUser()" />
</div>
</form>
Add ngMessages:
var demoApp = angular.module('demoApp', ['ngMessages']);
demoApp.controller("homeController", ["$scope", "$timeout", function ($scope, $timeout) {
$scope.loginUser = function () {
if($scope.loginform.$valid){
//Code to run before submitting (but not validation checks)
} else{
return false;
}
};
}]);
Don't forget to include ngMessages in your app declaration and include the ngMessages.js script file. Note how you can simply use HTML5 validators.
I found the thing I was looking for. In the end I had to create a directive for validating and then submitting. So I am posting it here as a whole answer.
My HTML
<div ng-controller="homeController" ng-init="construct()">
<form method="post" action="Index" role="form" id="loginform" name="loginform" ng-form-commit novalidate class="ng-pristine ng-invalid ng-invalid-required">
<div class="form-group">
<label for="UserName">User ID</label>
<input autocomplete="off" class="form-control ng-valid ng-touched ng-pristine ng-untouched ng-not-empty"
id="UserName" name="UserName" ng-model="user.UserName" type="text" value=""
ng-change="userNameValidation = user.UserName.length == 0">
<span class="field-validation-error text-danger" ng-show="userNameValidation">The User ID field is required.</span>
</div>
<div class="form-group">
<label for="Password">Password</label>
<input autocomplete="off" class="form-control ng-valid ng-touched ng-pristine ng-untouched ng-not-empty"
id="Password" name="Password" ng-model="user.Password" type="password" value=""
ng-change="passwordValidation = user.Password.length == 0">
<span class="field-validation-error text-danger" ng-show="passwordValidation">The Password field is required.</span>
</div>
<div>
<input type="button" id="btnLogin" title="Login" name="btnLogin" value="Login" ng-click="validateUser(loginform)" />
</div>
</form>
</div>
Look for ng-form-commit on the form element. It is the directive that I created.
My Angular code
var demoApp = angular.module('demoApp', []);
demoApp.factory("commonService", function () {
return {
isNullOrEmptyOrUndefined: function (value) {
return !value;
}
};
});
//This is the directive that helps posting the form back...
demoApp.directive("ngFormCommit", [function () {
return {
require: "form",
link: function ($scope, $el, $attr, $form) {
$form.commit = function () {
$el[0].submit();
};
}
};
}]);
demoApp.controller("homeController", ["$scope", "commonService", function ($scope, commonService) {
$scope.construct = function construct() {
$scope.user = { UserName: "", Password: "" };
};
$scope.userNameValidation = false;
$scope.passwordValidation = false;
$scope.isFormValid = false;
$scope.validateUser = function ($form) {
$scope.isFormValid = true;
$scope.userNameValidation = commonService.isNullOrEmptyOrUndefined($scope.user.UserName);
$scope.passwordValidation = commonService.isNullOrEmptyOrUndefined($scope.user.Password);
$scope.isFormValid = !($scope.userNameValidation || $scope.passwordValidation);
if ($scope.isFormValid === true) {
$scope.loginUser($form);
}
};
$scope.loginUser = function ($form) {
$form.commit();
};
}]);
I found the directive here
Example using Angular 1.5 components.
(function(angular) {
'use strict';
function DemoFormCtrl($timeout, $sce) {
var ctrl = this;
this.$onInit = function() {
this.url = $sce.trustAsResourceUrl(this.url);
/*$timeout(function() {
ctrl.form.$$element[0].submit();
});*/
};
this.validate = function(ev) {
console.log('Running validation.');
if (!this.form) {
return false;
}
};
}
angular.module('app', [])
.component('demoForm', {
template: `
<p>To run this demo allow pop-ups from https://plnkr.co</p>
<hr>
<p>AngularJS - submit form programmatically after validation</p>
<form name="$ctrl.form" method="get" target="blank" action="{{::$ctrl.url}}" novalidate
ng-submit="$ctrl.validate($event)">
<input type='hidden' name='q' ng-value='::$ctrl.value'>
<input type='hidden' name='oq' ng-value='::$ctrl.value'>
<input type="submit" value="submit...">
</form>`,
controller: DemoFormCtrl,
bindings: {
url: '<',
value: '<'
}
});
})(window.angular);
https://plnkr.co/edit/rrruj6vlWrxpN3od9YAj?p=preview
I would like to dynamically display Person and Address data using label and input value in Summary Section. As the user edits the form fields, a list items with label + value should display in the summary tables. If value has been removed in the form, that associated label and value should be removed from the Summary Section.
I have added client side validation for each input element. I tried to solve this and couldn't figure out what is best way to do it. Any help would be appreciated.
Example:
// the main (app) module
var myApp = angular.module("myApp", []);
// add a controller
myApp.controller("myCtrl", function($scope) {
$scope.vm = {
caller: {
person: {
firstName: '',
lastName: '',
phoneOne: '',
email: ''
},
address: {
lineOne: '',
lineTwo: ''
}
}
};
$scope.save = function() {
console.log($scope.vm);
}
});
// add a directive
myApp.directive('showErrors', function($timeout, $compile) {
return {
restrict: 'A',
require: '^form',
link: function(scope, el, attrs, formCtrl) {
// find the text box element, which has the 'name' attribute
var inputEl = el[0].querySelector("[name]");
// convert the native text box element to an angular element
var inputNgEl = angular.element(inputEl);
// get the name on the text box
var inputName = inputNgEl.attr('name');
// only apply the has-error class after the user leaves the text box
var blurred = false;
inputNgEl.bind('blur', function() {
blurred = true;
el.toggleClass('has-error', formCtrl[inputName].$invalid);
});
scope.$watch(function(scope) {
return formCtrl[inputName].$invalid;
}, function(invalid, scope) {
// we only want to toggle the has-error class after the blur
// event or if the control becomes valid
if (!blurred && invalid) {
return
}
el.toggleClass('has-error', invalid);
});
scope.$on('show-errors-check-validity', function() {
el.toggleClass('has-error', formCtrl[inputName].$invalid);
});
scope.$on('show-errors-reset', function() {
$timeout(function() {
el.removeClass('has-error');
}, 0, false);
});
}
}
});
.form-group .help-block {
display: none;
}
.form-group.has-error .help-block {
display: inline;
}
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp" ng-controller="myCtrl">
<form name="claimForm" ng-submit="save()">
<h3>PERSON</h3>
<div class="col-md-6">
<div class="form-group form-caller" show-errors>
<label class="control-label">First Name<span class="help-block" ng-if="claimForm.callerFirstName.$error.required"><i>[required]</i></span>
</label>
<input type="text" name="callerFirstName" ng-model="vm.caller.person.firstName" class="form-control" required="" />
</div>
</div>
<div class="col-md-6">
<div class="form-group form-caller" show-errors>
<label class="control-label">Last Name<span class="help-block" ng-if="claimForm.callerLastName.$error.required"><i>[required]</i></span>
</label>
<input type="text" name="callerLastName" ng-model="vm.caller.person.lastName" class="form-control" required="" />
</div>
</div>
<hr />
<h3>ADDRESS</h3>
<div class="col-md-6">
<div class="form-group" show-errors>
<label class="control-label">Address Line 1<span class="help-block" ng-if="claimForm.addressOne.$error.required"><i>[required]</i></span>
</label>
<input type="text" name="addressOne" ng-model="vm.caller.address.lineOne" class="form-control" required="" />
</div>
</div>
<div class="col-md-6">
<div class="form-group" show-errors>
<label class="control-label">Address Line 2<span class="help-block" ng-if="claimForm.addressTwo.$error.required"><i>[required]</i></span>
</label>
<input type="text" name="addressTwo" ng-model="vm.caller.address.lineTwo" class="form-control" required="" />
</div>
</div>
<hr />
<input type="submit" id="submit" value="SUBMIT" class="btn btn-primary btn-lg" />
{{vm | json }}
</form>
<h2>Summary</h2>
<div id="person">
<h3>PERSON </h3>
</div>
<hr />
<div id="address">
<h3>ADDRESS</h3>
</div>
</body>
Thanks in Advance
Here I created sample file for validation, which is working fine...
But My requirement is I need to do some modification on that while validating. Error message need to show in auto tooltip. It needs to be shown automatically when there is error and hide automatically once error cleared. Until error clear popup need to be stay.
If it is possible without jquery or else with jquery also fine.
var app = angular.module('myapp', ['UserValidation']);
myappCtrl = function($scope) {
$scope.formAllGood = function () {
return ($scope.usernameGood && $scope.passwordGood && $scope.passwordCGood)
}
}
angular.module('UserValidation', []).directive('validUsername', function () {
return {
require: 'ngModel',
link: function (scope, elm, attrs, ctrl) {
ctrl.$parsers.unshift(function (viewValue) {
// Any way to read the results of a "required" angular validator here?
var isBlank = viewValue === ''
var invalidChars = !isBlank && !/^[A-z0-9]+$/.test(viewValue)
var invalidLen = !isBlank && !invalidChars && (viewValue.length < 5 || viewValue.length > 20)
ctrl.$setValidity('isBlank', !isBlank)
ctrl.$setValidity('invalidChars', !invalidChars)
ctrl.$setValidity('invalidLen', !invalidLen)
scope.usernameGood = !isBlank && !invalidChars && !invalidLen
})
}
}
}).directive('validPassword', function () {
return {
require: 'ngModel',
link: function (scope, elm, attrs, ctrl) {
ctrl.$parsers.unshift(function (viewValue) {
var isBlank = viewValue === ''
var invalidLen = !isBlank && (viewValue.length < 8 || viewValue.length > 20)
var isWeak = !isBlank && !invalidLen && !/(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z])/.test(viewValue)
ctrl.$setValidity('isBlank', !isBlank)
ctrl.$setValidity('isWeak', !isWeak)
ctrl.$setValidity('invalidLen', !invalidLen)
scope.passwordGood = !isBlank && !isWeak && !invalidLen
})
}
}
}).directive('validPasswordC', function () {
return {
require: 'ngModel',
link: function (scope, elm, attrs, ctrl) {
ctrl.$parsers.unshift(function (viewValue, $scope) {
var isBlank = viewValue === ''
var noMatch = viewValue != scope.myform.password.$viewValue
ctrl.$setValidity('isBlank', !isBlank)
ctrl.$setValidity('noMatch', !noMatch)
scope.passwordCGood = !isBlank && !noMatch
})
}
}
})
<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.2.2/css/bootstrap-combined.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myapp">
<form name="myform" class="form form-horizontal" ng-controller="myappCtrl" novalidate>
<legend>Angular User Validation with Bootstrap Decorations</legend>
<div class="control-group" ng-class="{error:!myform.username.$valid}">
<label for="inputUsername" class="control-label">Username:</label>
<div class="controls">
<input type="text" id="inputUsername" name="username" ng-model="username" valid-username />
<div class="help-inline">
<span ng-show="!!myform.username.$error.isBlank">Username Required.</span>
<span ng-show="!!myform.username.$error.invalidChars">Username must contain letters & spaces only.</span>
<span ng-show="!!myform.username.$error.invalidLen">Username must be 5-20 characters.</span>
</div>
</div>
</div>
<div class="control-group" ng-class="{error:!myform.password.$valid}">
<label for="inputPassword" class="control-label">Password:</label>
<div class="controls">
<input type="text" id="inputPassword" name="password" ng-model="password" valid-password />
<div class="help-inline">
<span ng-show="!!myform.password.$error.isBlank">Password Required.</span>
<span ng-show="!!myform.password.$error.isWeak">Must contain one upper & lower case letter and a non-letter (number or symbol.)</span>
<span ng-show="!!myform.password.$error.invalidLen">Must be 8-20 characters.</span>
</div>
</div>
</div>
<div class="control-group" ng-class="{error:!myform.password_c.$valid}">
<label for="password_c" class="control-label">Confirm Password:</label>
<div class="controls">
<input type="text" id="password_c" name="password_c" ng-model="password_c" valid-password-c />
<div class="help-inline">
<span ng-show="!!myform.password_c.$error.isBlank">Confirmation Required.</span>
<span ng-show="!!myform.password_c.$error.noMatch">Passwords don't match.</span>
</div>
</div>
</div>
<div class="form-actions" ng-show="formAllGood()">
<input type="submit" class="btn btn-primary" value="Submit" />
</div>
</form></div>
Yes it is possible to show/hide popover on any event. Following code depicts a validate function for numbers using popover.
JSFiddle.
function validate(el) {
var regex = /^\d+$/g;
var valid = regex.test(el.value);
if (!valid) {
// Check if popover is already visible to handle flicker effect.
if ($("#txtInput").next('div.popover').length == 0) {
$('#txtInput').popover({
placement: 'bottom',
content: 'This is not a valid entry'
}).popover('show');
}
} else {
$('#txtInput').popover('hide');
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<input type="text" id="txtInput" onkeyup="validate(this)">
References:
Check visibility
Documentation.
Best solution is to use Parsley.js
Why Parsley :
Validation Event can be customized (onsubmit , onkeyup , or any other event )
Validation Style can be customized
Validation message will automatically disappear , once input satisfies conditions
Check their examples