I have faced with the unclear situation when I try to setValidity() inside my own directive.
It set opposite value than expression when, expression return false, and undefined when returned return true.
So my Angular code:
<script>
var userForm = angular.module("userForm", []);
userForm.directive('isEquals', function () {
return {
// element must have ng-model attribute.
require: 'ngModel',
scope: {
otherFieldValue: "=isEquals"
},
link: function (scope, elem, attr, ctrl) {
ctrl.$validators.isEquals = function (modelValue) {
console.log("otherFieldValue: " + scope.otherFieldValue);
console.log("modelValue: " + modelValue);
valid = (modelValue === scope.otherFieldValue);
ctrl.$setValidity('isEquals', valid);
console.log("valid: " + valid);
//Q1: is it in fact userForm.confirmPassword.$error.isEquals?
console.log("isEquals: " + ctrl.$error.isEquals);
console.log("modelValue: " + modelValue);
console.log("");
return modelValue;
};
scope.$watch("otherFieldValue", function () {
ctrl.$validate();
});
}
};
});
userForm.controller("userFormController", function ($scope, $http) {
});
</script>
and my html code:
<div ng-app="userForm">
<form name="userForm" modelAttribute="userForm" ng-controller="userFormController" ng-submit="createUser()" novalidate>
<div class="row">
<input id="password" name="password" path="password" type="password" placeholder="Password" minlength="5" maxlength="60" ng-model="user.password" required/>
<br>
<span ng-show="userForm.password.$dirty && userForm.password.$error.required">Password field is required.<br></span>
<span ng-show="userForm.password.$dirty && userForm.password.$error.minlength || userForm.password.$error.maxlength">Password field must have size from 5 to 60 symbols.<br></span>
</div>
<div class="row">
<input id="confirmPassword" name="confirmPassword" path="confirmPassword" type="password" placeholder="Confirm Password" minlength="5" maxlength="60" ng-model="user.confirmPassword" equals-to="user.password" required/>
<br>
<span ng-show="userForm.confirmPassword.$dirty && userForm.confirmPassword.$error.required">Confirm Password field is required.<br></span>
<span ng-show="userForm.confirmPassword.$dirty && userForm.confirmPassword.$error.minlength || userForm.confirmPassword.$error.maxlength">Confirm Password field must have size from 5 to 60 symbols.<br></span>
<span id="m1" ng-show="userForm.confirmPassword.$dirty && !userForm.confirmPassword.$error.equalsTo">Passwords are not same.<br></span>
</div>
<div class="row">
<input id="submit" type="submit" ng-submit="createUser()" value="Sign Up"/>
</div>
</form>
</div>
But when I enter passwords i have the next situations (I will sign "Passwords are not same." AS m1) :
//1) valid!=equalsTo, m1 visible. Have to be valid===equalsTo===false, m1 visible.
otherFieldValue: teste
modelValue: undefined
valid: false
equalsTo: true
modelValue: undefined
//2) valid!=equalsTo, equalsTo undefined. Have to be valid===equalsTo===true. m1 still visible, but has not to be.
otherFieldValue: teste
modelValue: teste
valid: true
equalsTo: undefined
modelValue: teste
I will appreciate any help, propositions, link and especially explanations. Thanks in advance.
EDIT: OK. Accidentally, I figured out that it is because the directive's name and ctrl.$validators.isEquals have the same names. What is the problem with that, can someone explain?
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.
Here i am facing the problem regarding below specified third point (when user changes password value).
Test Scenario:
user enters all field properly - [Button Enabled]
if password field is invalid as it doesn't meet the password strength then the create an account button is in disable mode.
If user changes password value but the password field is valid. EX: [Yash#123 to Yash#1234]
here confirmation field value is Yash#123. then button should be in disable mode.
I have tested by accessing Parent Scope, Scope values between two directives like this.
function okPasswordDirective() {
$element.on('blur change keydown', function( evt ) {
if( ngPasswordModel.$valid ) {
$scope.passwordVal = ngPasswordModel.$viewValue;
console.log('Updated Val : ', $scope.passwordVal);
$scope.updatePass();
}
}
}
function compareToDirective() {
//use scope.$parent to associate the function called to directive function
scope.$parent.updatePass = function() {
console.log('$watch « Password Element Watcher.')
console.log('Pswd: ',scope.$parent.passwordVal, '\t Cnfirm:', ngModel.$modelValue);
//scope.registerForm.confirm.$invalid = true;
}
}
Here in updatePass() function iam not receiving the lastcommited value of password. When i click on confirm field it used to get.
but no use, i am unable to disable the button by making confirm field as invalid.
var pswd = angular.element(document.getElementById('password')).scope().registerForm.password;
var cnfm = angular.element(document.getElementById('confirmedID')).scope().registerForm.confirm;
console.log('PSWD:', pswd, '\n CNFM:', cnfm);
console.log('Diff : ', pswd.$viewValue != cnfm.$viewValue);
if( pswd.$viewValue != cnfm.$viewValue ) {
console.log('Result : ', (pswd.$dirty && cnfm.$dirty && cnfm.$valid && ( pswd.$viewValue != cnfm.$viewValue ) ) ? 'error' : 'noErr');
cnfm.$invalid = true;
}
Registration Form Code: fiddle
<!-- HTML CODE -->
<body ng-app="loginModule">
<div class="main-container">
<div class="form-container">
<h2 class="form-label">Sign Up</h2>
<div class="form-container" data-ng-controller="registerController" >
<form name="registerForm" role="form" data-ng-submit="formSubmit()">
<div class="form-group"><!-- Display Name -->
<div class="row">
<div class="col-md-6 col-sm-6 col-xs-6 left">
<div class="error form-hint"
data-ng-show="registerForm.firstname.$dirty && registerForm.firstname.$error.required"
data-ng-cloak>{{"This field is required."}}
</div>
<input type="text" class="form-control" name="firstname" placeholder="First name"
data-ng-class="(registerForm.firstname.$dirty && registerForm.firstname.$invalid) ? 'error' : ''"
data-ng-required="true" data-ng-model="firstName">
</div>
<div class="col-md-6 col-sm-6 col-xs-6 right">
<div class="error form-hint"
data-ng-show="registerForm.lastname.$dirty && registerForm.lastname.$error.required"
data-ng-cloak>{{"This field is required."}}
</div>
<input type="text" class="form-control" name="lastname" placeholder="Last name"
data-ng-class="(registerForm.lastname.$dirty && registerForm.lastname.$invalid) ? 'error' : ''"
data-ng-required="true" data-ng-model="lastName">
</div>
</div>
</div>
</div>
</div>
<div class="form-group">
<div class="error form-hint"
data-ng-show="registerForm.username.$dirty && registerForm.username.$error.required"
data-ng-cloak>{{"This field is required."}}
</div>
<input type="text" class="form-control" id="userid" name="username" placeholder="User name"
data-ng-class="(registerForm.username.$dirty && registerForm.username.$invalid) ? 'error' : ''"
data-ng-required="true" data-ng-model="username">
</div>
<div class="form-group">
<div class="error form-hint"
data-ng-show="registerForm.email.$dirty && registerForm.email.$error.required"
data-ng-cloak>{{"You can't leave this empty."}}
</div>
<div class="error form-hint"
data-ng-show="registerForm.email.$dirty && registerForm.email.$error.email"
data-ng-cloak>{{"The email address you provided isn't valid"}}</div>
<input type="email" class="form-control" id="emailid" name="email" placeholder="Email address"
data-ng-class="(registerForm.email.$dirty && registerForm.email.$invalid) ? 'error' : ''"
data-ng-required="true" data-ng-model="email77">
</div>
<div class="form-group">
<div class="form-hint">
To conform with our Strong Password policy,
Use at least one letter, one numeral, one special character, and seven characters.
</div>
<input type="text" class="form-control" data-ok-password-directive
id="password" name="password" placeholder="Password" data-ng-required="true"
data-ng-class="(registerForm.password.$dirty && registerForm.confirm.$dirty
&& registerForm.confirm.$valid &&
( registerForm.password.$viewValue != registerForm.confirm.$viewValue ) ) ? 'error' : ''"
data-ng-model="passwordModel">
<div class="label password-count"
data-ng-class="passwordModel.length > 7 ? 'label-success' : 'label-danger'"
data-ng-cloak>{{ passwordModel | passwordCountFilter }}</div>
<div class="strength-meter">
<div class="strength-meter-fill" data-strength="{{myModulePasswordMeter}}"></div>
</div>
</div>
<div class="form-group">
<div class="error form-hint"
data-ng-show="registerForm.confirm.$dirty && !registerForm.confirm.$empty && registerForm.confirm.$error.required"
data-ng-cloak>{{"You can't leave this empty."}}
</div>
<div class="error form-hint"
data-ng-show="registerForm.confirm.$dirty && registerForm.confirm.$invalid && !registerForm.confirm.$error.required"
data-ng-cloak>{{"These passwords don't match. Try again?"}}</div>
<div class="error form-hint" data-ng-show="
( registerForm.confirm.$dirty && registerForm.confirm.$valid && !registerForm.confirm.$invalid) &&
( registerForm.password.$modelValue != registerForm.confirm.$modelValue )" data-ng-cloak>
{{'Password mismatch'}}
</div>
<!-- Enter to Confirm password | Enter for Password confirmation -->
<input type="text" class="form-control" id="confirmedID" name="confirm"
placeholder="Password confirmation"
data-ng-required="true" data-ng-model="confirm77"
data-ng-class="(registerForm.confirm.$dirty &&
( registerForm.confirm.$invalid ||
( registerForm.password.$modelValue != registerForm.confirm.$modelValue ) ) ) ? 'error' : ''"
data-compare-to="registerForm.password" >
</div>
<button id="siginButton" type="submit" class="btn" data-ng-disabled="registerForm.$invalid">Create an account</button>
</form>
</div>
</div>
</div>
</body>
Script Code:
(function() {
var loginModule = angular.module('loginModule', []);
loginModule.constant('USERCONSTANTS', (function() {
return {
PASSWORD_LENGTH: 7
}
})());
loginModule.controller('registerController', ['$scope','$http', '$window', '$location', registerControllerFun]);
function registerControllerFun($scope, $http, $window, $location) {
console.log(' registerControllerFun...');
}
loginModule.factory('myfactory', [function() {
return {
score: function() {
//console.log('arguments List : ', arguments);
var score = 0, value = arguments[0], passwordLength = arguments[1];
var containsLetter = /[a-zA-Z]/.test(value), containsDigit = /\d/.test(value), containsSpecial = /[^a-zA-Z\d]/.test(value);
var containsAll = containsLetter && containsDigit && containsSpecial;
console.log(" containsLetter - ", containsLetter,
" : containsDigit - ", containsDigit,
" : containsSpecial - ", containsSpecial);
if( value.length == 0 ) {
score = 0;
} else {
if( containsAll ) {
score += 3;
} else {
if( containsLetter ) score += 1;
if( containsDigit ) score += 1;
if( containsSpecial ) score += 1;
}
if(value.length >= passwordLength ) score += 1;
}
/*console.log('Factory Arguments : ', value, " « Score : ", score);*/
return score;
}
};
}]);
loginModule.directive('okPasswordDirective', ['myfactory', 'USERCONSTANTS', function(myfactory, USERCONSTANTS) {
return {
restrict: 'AC',
// use the NgModelController
require: 'ngModel',
// add the NgModelController as a dependency to your link function
link: function($scope, $element, $attrs, ngPasswordModel) {
console.log('Directive - USERCONSTANTS.PASSWORD_LENGTH : ', USERCONSTANTS.PASSWORD_LENGTH);
$element.on('blur change keydown', function( evt ) {
$scope.$evalAsync(function($scope) {
var pwd = $scope.password = $element.val();
$scope.myModulePasswordMeter = pwd ? (pwd.length > USERCONSTANTS.PASSWORD_LENGTH
&& myfactory.score(pwd, USERCONSTANTS.PASSWORD_LENGTH) || 0) : null;
ngPasswordModel.$setValidity('okPasswordController', $scope.myModulePasswordMeter > 3);
});
if( ngPasswordModel.$valid ) {
$scope.passwordVal = ngPasswordModel.$viewValue;
console.log('Updated Val : ', $scope.passwordVal);
$scope.updatePass();
}
});
}
};
}]);
loginModule.filter('passwordCountFilter', [ function() {
var passwordLengthDefault = 7;
return function( passwordModelVal ) {
passwordModelVal = angular.isString(passwordModelVal) ? passwordModelVal : '';
var retrunVal = passwordModelVal &&
(passwordModelVal.length > passwordLengthDefault ? passwordLengthDefault + '+' : passwordModelVal.length);
return retrunVal;
};
} ]);
var compareTo = function() {
return {
require: "ngModel",
// directive defines an isolate scope property (using the = mode) two-way data-binding
scope: {
passwordEleWatcher: "=compareTo"
},
link: function(scope, element, attributes, ngModel) {
console.log('Confirm Password Link Function call.');
var pswd = scope.passwordEleWatcher;
ngModel.$validators.compareTo = function( compareTo_ModelValue ) {
//console.log('scope:',scope);
if( (pswd != 'undefined' && pswd.$$rawModelValue != 'undefined') && (pswd.$valid && pswd.$touched) ) {
var pswdModelValue = pswd.$modelValue;
var isVlauesEqual = ngModel.$viewValue == pswdModelValue;
return isVlauesEqual;
} else {
console.log('Please enter valid password, before conforming the password.');
return false;
}
};
scope.$watch("passwordEleWatcher", function() {
console.log('$watch « Confirm-Password Element Watcher.')
ngModel.$validate();
});
scope.$parent.updatePass = function() {
console.log('$watch « Password Element Watcher.')
console.log('Pswd: ',scope.$parent.passwordVal, '\t Cnfirm:', ngModel.$modelValue);
//scope.registerForm.confirm.$invalid = true;
}
},
};
};
loginModule.directive("compareTo", compareTo);
})(window.angular);
Any help will be appreciated.
CSS classes Observed:
ng-pristine ng-untouched ng-empty ng-invalid ng-invalid-required form-control ng-isolate-scope ng-invalid-compare-to
ng-pristine ng-touched ng-empty ng-invalid ng-invalid-required form-control ng-isolate-scope ng-invalid-compare-to
ng-dirty ng-valid-parse ng-touched ng-not-empty ng-invalid ng-valid-required error form-control ng-isolate-scope ng-invalid-compare-to
ng-dirty ng-valid-parse ng-touched ng-empty ng-invalid ng-valid-required error form-control ng-isolate-scope ng-invalid-compare-to
ng-dirty ng-valid-parse ng-touched ng-not-empty ng-valid ng-valid-required form-control ng-isolate-scope ng-valid-compare-to
I just want to change css value from ng-valid to ng-invalid
Just added expression [To evaluate equality of password and conformation password] to the ng-disabled- Directive of a Button.
Code « Updated Fiddle
<button id="siginButton" type="submit" class="btn" data-ng-disabled="registerForm.$invalid">
Create an account
</button>
<!-- Changed to -->
<button id="siginButton" type="submit" class="btn"
data-ng-disabled="registerForm.$invalid
|| ( registerForm.confirm.$dirty && registerForm.confirm.$valid && !registerForm.confirm.$invalid )
&& ( registerForm.password.$modelValue != registerForm.confirm.$modelValue )">
Create an account
</button>
Confirm Password field with validation messages.
You can't leave this empty.
Confirm password with our Strong Password Policy.
These passwords don't match. Try again?
Solutions:
Disable Conformation Password field when the password field is invalid.
Updated Fiddle
User ng-pattern attribute to confirm. Updated Fiddle
Example:
<form name="registerForm" role="form" data-ng-submit="formSubmit()">
Password:<input type="password" name="password" ng-model="password77">
ConfirmPassword:<input type="password" name="confirm" ng-model="confirm77" ng-pattern="emailReg">
<div class="error form-hint" ng-messages="registerForm.confirm.$error" data-ng-show="registerForm.confirm.$dirty">
<p ng-show="registerForm.confirm.$error.required" ng-message="required">{{"You can't leave this empty."}}</p>
<p ng-show="!(registerForm.confirm.$error.pattern && registerForm.confirm.$error.required) && registerForm.password.$invalid && !registerForm.confirm.$invalid" ng-message="pattern">{{"Confirm Password with our strong password policy!"}}</p>
<p ng-show="registerForm.confirm.$invalid && !registerForm.confirm.$error.required && registerForm.confirm.$error.pattern" ng-message="">{{"These passwords don't match. Try again?"}}</p>
</div>
</form>
I am trying to build a custom directive (based on an example I saw) to ensure that the confirm password is correct.
I am running into some trouble with the $setValidity tag, although all my console.log() execute and print out, it does not seem that the validity is being updated. Pass stays true even when I read in my console "set to false".
I made sure the name and the ng-model are the same and I also tried using scope.$apply, but that would comeout with an error saying i was trying to apply when something else is being applied.
Here is my code:
HTML
<form ng-submit="signup()" name="profileForm">
<div class="form-group">
<label class="form-label" for="input-example-2">Password</label>
<input class="form-input" ng-model="pnew" type="password" name="pnew" placeholder="Password" required>
</div>
<div class="form-group">
<label class="form-label" for="input-example-2">Confirm Password</label>
<input class="form-input" name="confirm" ng-model="confirm" type="password" placeholder="Password" required pwcheck>
</div>
{{profileForm.confrim.$error.pass}}
<hr>
{{profileForm.confirm.$error}}
<hr>
{{profileForm.confirm.$valid}}
<span ng-show="profileForm.confirm.$error.pwCheck"> the passwords dont match</span>
<div class="form-group">
<button class="btn btn-primary">Sign up</button>
</div>
</form>
JS code for the pwcheck directive
.directive('pwcheck', function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
function valid(value){
scope.$watch("confirm", function(newval, oldval){
console.log(value);
console.log(scope.pnew);
if(value==scope.pnew){
console.log("success!");
ctrl.$setValidity('pass', true);
return value;
}
else {
console.log("set to false");
ctrl.$setValidity('pass', false);
return undefined;
}
});
}
ctrl.$parsers.push(valid);
} } });
No need to use $watch on confirm if you're using your directive on same element & having ng-model in require. So your code can be
ctrl.$parsers.unshift(valid);
ctrl.$formatters.unshift(valid);
function valid(viewValue){
console.log(viewValue);
console.log(scope.pnew);
if(viewValue==scope.pnew){
console.log("success!");
ctrl.$setValidity('pass', true);
return viewValue;
}
else {
console.log("set to false");
ctrl.$setValidity('pass', false);
return undefined;
}
}
Most trivial example plunk
https://plnkr.co/edit/vPbICfSCDnwHKh07DAXJ?p=preview
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
So, what the problem. I have two input fields newPassword and oldPassword. I want to check if these two fields are equals show the error message.
Form looks like:
<form name="passwordForm" ng-submit="submitPasswordForm()" modelAttribute="userPasswordChange" novalidate>
<div class="row">
<input path="oldPassword" type="password" id="oldPassword" name="oldPassword" placeholder="Old Password" ng-model="user.oldPassword" minlength="5" maxlength="128" required/>
<br>
<span ng-show="passwordForm.oldPassword.$dirty && passwordForm.oldPassword.$error.required">Old Password field can not be empty. Please check it and try again.</span>
<span ng-show="passwordForm.oldPassword.$error.minlength || passwordForm.oldPassword.$error.maxlength">Old password field size must be between 5 and 128</span>
</div>
<div class="row">
<input path="newPassword" type="password" id="newPassword" name="newPassword" placeholder="New Password" ng-model="user.newPassword" minlength="5" maxlength="128" required diff-values="oldPassword"/>
<br>
<span ng-show="passwordForm.newPassword.$dirty && passwordForm.newPassword.$error.required">New Password field can not be empty. Please check it and try again.</span>
<span ng-show="passwordForm.newPassword.$error.minlength || passwordForm.oldPassword.$error.maxlength">New Password field size must be between 5 and 128</span>
<span ng-show="passwordForm.newPassword.$dirty && passwordForm.newPassword.$error.differentValues">New Password and Old Password fields must have different values.</span>
</div>
<div class="row">
<input path="confirmPassword" type="password" id="confirmPassword" name="confirmPassword" placeholder="Confirm password" ng-model="user.confirmPassword" minlength="5" maxlength="128" same required/>
<br>
<span ng-show="passwordForm.confirmPassword.$dirty && passwordForm.confirmPassword.$error.required">Confirm password field can not be empty. Please check it and try again.</span>
<span ng-show="passwordForm.confirmPassword.$error.minlength || passwordForm.oldPassword.$error.maxlength">Confirm password field size must be between 5 and 128</span>
</div>
<div class="row">
<input id="save" type="submit" value="Save" class="btn btn-primary" onsubmit="submitPasswordForm()"
ng-disabled="passwordForm.oldPassword.$dirty && passwordForm.oldPassword.$invalid
|| passwordForm.newPassword.$dirty && passwordForm.newPassword.$invalid
|| passwordForm.confirmPassword.$dirty && passwordForm.confirmPassword.$invalid"/>
</div>
</form>
So if I have understood right, I have to create my own directive. So I realized it in this way:
var postPasswordForm = angular.module('postPasswordForm', []);
postPasswordForm.directive('diffValues', function () {
return {
restrict: "A",
link: function (scope, elem, attr, ctrl) {
ctrl.$parsers.push(function (value) {
var compareWith = document.getElementById(attr.diffValues).value;
var currentVar = value;
ctrl.$setValidity('differentValues', compareWith !== currentVar);
console.log(scope);
return value;
});
}
};
});
The problem is that for this task I also need to observe when old password change, and according to expression show\hide this span:
<span ng-show="passwordForm.newPassword.$dirty && passwordForm.newPassword.$error.differentValues">New Password and Old Password fields must have different values.</span>
and of course change this value
passwordForm.newPassword.$error.differentValues:
Can someone help me and explain how to do that in the right way? I will appreciate any idea, explanations, and links.
Thanks in advance.
I have solved that in a next way:
<form name="passwordForm" ng-submit="submitPasswordForm()" modelAttribute="userPasswordChange" novalidate>
<div class="row">
<input path="oldPassword" type="password" id="oldPassword" name="oldPassword" placeholder="Old Password" ng-model="user.oldPassword" minlength="5" maxlength="128" required/>
<br>
<span ng-show="passwordForm.oldPassword.$dirty && passwordForm.oldPassword.$error.required">Old Password field can not be empty. Please check it and try again.</span>
<span ng-show="passwordForm.oldPassword.$error.minlength || passwordForm.oldPassword.$error.maxlength">Old password field size must be between 5 and 128</span>
</div>
<div class="row">
<input path="newPassword" type="password" id="newPassword" name="newPassword" placeholder="New Password" ng-model="user.newPassword" minlength="5" maxlength="128" required diff-values="user.oldPassword"/>
<br>
<span ng-show="passwordForm.newPassword.$dirty && passwordForm.newPassword.$error.required">New Password field can not be empty. Please check it and try again.</span>
<span ng-show="passwordForm.newPassword.$error.minlength || passwordForm.oldPassword.$error.maxlength">New Password field size must be between 5 and 128</span>
**CHANGED HERE:**<span ng-show="passwordForm.newPassword.$dirty && passwordForm.newPassword.$error.differentValues">New Password field must be different from the Old Password field.</span>
</div>
<div class="row">
<input path="confirmPassword" type="password" id="confirmPassword" name="confirmPassword" placeholder="Confirm password" ng-model="user.confirmPassword" minlength="5" maxlength="128" same required/>
<br>
<span ng-show="passwordForm.confirmPassword.$dirty && passwordForm.confirmPassword.$error.required">Confirm password field can not be empty. Please check it and try again.</span>
<span ng-show="passwordForm.confirmPassword.$error.minlength || passwordForm.oldPassword.$error.maxlength">Confirm password field size must be between 5 and 128</span>
</div>
<div class="row">
<input id="save" type="submit" value="Save" class="btn btn-primary" onsubmit="submitPasswordForm()"
ng-disabled="passwordForm.oldPassword.$dirty && passwordForm.oldPassword.$invalid
|| passwordForm.newPassword.$dirty && passwordForm.newPassword.$invalid
|| passwordForm.confirmPassword.$dirty && passwordForm.confirmPassword.$invalid"/>
</div>
</form>
And directive function changed to this one:
postPasswordForm.directive('diffValues', function () {
return {
restrict: "A",
require: 'ngModel',
scope: {
otherModelValue: "=diffValues"
},
link: function (scope, elem, attr, ctrl) {
ctrl.$validators.diffValues = function (modelValue) {
ctrl.$setValidity('differentValues', modelValue !== scope.otherModelValue);
};
scope.$watch("otherModelValue", function () {
ctrl.$validate();
});
}
};
});
I started to use angular yesterday first time, so sorry if ask some simple things. And as I understood this one it is not the better solutions because from the documentation I can read that $validate() - invoke all validators from the $validators collection. But I need to run just one of them. Can I do that somehow? Or this solution is OK?