Angular form validation with skip some fields - javascript

I have a page which has a form in it named as profile updation and when a user comes to this page for any updation of his profile that time he only update 1 or 2 fields so every time form checks the form is valid or not then only saves in db, but I want to save if password and confirm password fields are not updated then also update his profile, but also when he wants to change password that time save button will get disabled and checks validation after that update the profile.
Means when user update only name that time also update the profile and also user update the password that time first check validation and then update the profile.
Save and isValid check:
app.controller('DemoCtrl', function($scope, $http) {
$scope.saveProfile = function(){
if($scope.profile.$valid){
ngProgress.start();
user.saveProfile($scope.currentUser.details,function(response){
angular.copy(response,shared.data.currentUser);
notification.success($filter("il8n")("_ProfileUpdateMessage_"));
ngProgress.done();
});
}
}
$scope.isValidForm = function(){
//if(($scope.profile.confirmpassword && $scope.profile.newpassword && $scope.profile.newpassword.$modelValue !== $scope.profile.confirmpassword.$modelValue))
// return true;
if(!$scope.profile.$valid){
if(($scope.profile.confirmpassword && $scope.profile.newpassword && $scope.profile.confirmpassword.$modelValue && $scope.profile.newpassword.$modelValue && ($scope.profile.newpassword.$modelValue.length == 0 || $scope.profile.confirmpassword.$modelValue.length == 0))){
return false;
}
if(($scope.profile.confirmpassword && $scope.profile.newpassword && $scope.profile.confirmpassword.$modelValue && $scope.profile.newpassword.$modelValue && $scope.profile.newpassword.$modelValue === $scope.profile.confirmpassword.$modelValue)){
return false;
}
}
if($scope.profile.$valid && $scope.profile.$dirty)
return false;
if($scope.profile.newpassword.$invalid || $scope.profile.newpassword.$dirty && $scope.profile.confirmpassword.$invalid || $scope.profile.confirmpassword.$dirty){
//$scope.profile.newpassword.$valid;
//$scope.profile.confirmpassword.$valid;
return false;
}
//if($scope.profile.newpassword.empty && $scope.profile.confirmpassword.empty ){
// return true;
//}
return true;
}
});
Find plnkr here.

As I see it, you want form where user can update few fields then update them?
About password change, I think you should split profile information from password change into two separate forms, where user can change password without changing other data. Then if user wants to change other user data (which is binded to ng-model and placed already into text boxes), then user change data and saves them.
Problem solved. If u want so, i can try to edit your plunk and show how it would look like :)
Plunk - New format
<form ng-submit="SAVE FUNCTION HERE">
<fieldset>
<div class="row">
<div class="col-sm-4">
<label class="proxima-nova nova-bold form-label">Change Password</label>
</div>
</div>
<div class="row">
<div class="col-sm-3">
<label data-ng-class="{'state-error': profile.newpassword.$invalid && profile.newpassword.$dirty && profile.newpassword.$error.strongPassword}">
<input type="password" class="form-control" placeholder="Enter new password" data-ng-model="currentUser.details.password" name="newpassword" data-password-check="currentUser.details.password" />
</label>
<div class="ng-cloak invalid" data-ng-show=" profile.newpassword.$error.strongPassword && profile.newpassword.$dirty && profile.newpassword.$invalid">
Password should contain atleast one special character, number, uppercase letter, and atleast 8 characters.
</div>
</div>
<div class="col-sm-3">
<label data-ng-class="{'state-error': profile.confirmpassword.$dirty && currentUser.details.password != currentUser.details.password_confirmation}">
<input type="password" class="form-control" placeholder="Confirm password" data-ng-model="currentUser.details.password_confirmation" name="confirmpassword" />
</label>
<div class="ng-cloak invalid" data-ng-show="profile.confirmpassword.$dirty && currentUser.details.password != currentUser.details.password_confirmation">
Passwords do not match
</div>
</div>
</div>
</fieldset>
</form>
Also in form fieldset you can add save button with type="submit", then that button will call that function which is defined into form tag
<form ng-submit="SAVE FUNCTION HERE">

Related

Difficulties with displaying error messages

When i try to call the form id's and tell the code if i click submit and the username and password fields are empty display "Please enter both login and password." and when there's text on the fields it displays "please stand by" None of this is displaying and i'm not sure what i'm doing wrong
$(document).ready(function() {
$("#login").click(function() {
$("#login").toggleClass('minus');
$("form").slideToggle(1000);
$("form").submit(function(){
if ("#username" == "" || "#pw" == "") {
$("#error").text("Please enter both login and password.");
} else {
$("#error").text("Please stand by");
}
});
}); // end click
}); // end ready
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<p>
<label for="username">Username:</label>
<input type="text" name="username" id="username">
</p>
<p>
<label for="pw">Password:</label>
<input type="password" name="pw" id="pw">
</p>
<p>
<input type="button" value="Submit">
</p>
<!-- placeholder for response if form data is correct/incorrect -->
<p id="error"> </p>
</form>
You are not comparing the value of these elements but are comparing if f.e. the string "#username" is equal to "", which it of course will never be. You need to actually retrieve the value of your element by using val().
So you might instead do this:
if ($("#username").val() == "" || $("#pw").val() == "") {
$("#error").text("Please enter both login and password.");
}
Also maybe have a look at the documentation for further help http://api.jquery.com/val/
Here is fiddle
Also make your input submit button as type "submit" and check the ".val()" of your inputs
$("#login").click(function() {
$("#login").toggleClass('minus');
$("form").slideToggle(1000);
}); // end click
$("form").submit(function(e) {
e.preventDefault();
if ( $("#username").val() === "" || $("#pw").val() === "" ) {
$("#error").text("Please enter both login and password.");
} else {
$("#error").text("Please stand by");
}
});

How to implement form validations for Dynamically generated Form fields

I have a page in my Angular application where all form fields are created dynamically based on data coming from backend.
<div class="col-md-12">
<form class="form-inline" name="reportsForm">
<div class="form-group form-group-grid" ng-repeat="fields in selectedTabData.requiredField" ng-switch="fields.paramType">
<label>{{fields.paramName}}<span class="asterisk" ng-if="fields.mandatory==true">*</span></label>
<input type="number" class="form-control" ng-switch-when="Number" ng-model="fields.fieldValue" ng-required="fields.mandatory">
<input type="date" data-date-format="mm/DD/YYYY" class="form-control" ng-switch-when="DatePicker" ng-model="fields.fieldValue" ng-required="fields.mandatory">
<input type="text" class="form-control" ng-switch-when="Text" ng-model="fields.fieldValue" ng-required="fields.mandatory">
<select type="date" class="form-control" ng-switch-when="DropDown" ng-options="field.paramKey as field.paramValue for field in fields.paramData" ng-model="fields.fieldValue" ng-required="fields.mandatory">
</select>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary form-inline-grid-button" ng-click="getReport()">Run Report</button>
</div>
</form>
<span style="color:red">Please enter all the required fields marked with (*)</span>
</div>
I need the validation error message to be shown if anyone of the required field in the form is left empty.
The form fields data coming from backend is assigned in $scope.selectedTabData.requiredField
$scope.selectedTabData.requiredField.forEach(function(item)
{
if(item.paramType == "DatePicker")
{
var date = new Date(item.fieldValue);
var formattedDate = (date.getMonth() + 1) + '/' + date.getDate() + '/' + date.getFullYear();
paramValue.push(formattedDate);
paramName.push(item.paramName);
}
else
{
if(item.mandatory == true && item.fieldValue == undefined){
//need to set validation as failed
}else{
//need to set validation as passed
}
paramValue.push(item.fieldValue);
paramName.push(item.paramName);
}
})
This is the condition I need to check to validate the form :
if(item.mandatory == true && item.fieldValue == undefined){
//need to set validation as failed
}else{
//need to set validation as passed
}
This is the first time I am working with dynamic fields, can anyone help me with implementation of validation in this case?
Thanks.
So to fix this, I had to deal with this the basic way.
I created a scope variable and set it as a flag.
in HTML :
<div>
<span ng-if="formInvalid" style="color:red">Please fill in all the required fields(*)</span>
</div>
In Controller :
$scope.formInvalid = false;
if(item.mandatory == true && item.fieldValue==null)
{
$scope.formInvalid = true;
}
This worked out for me. Please add more answers if you have an alternate solution to handle validations in dynamic elements.

HTML5 custom validation for passwords

I'm looking to create an HTML5 custom validation message when I enter 2 passwords which don't match.
Here's my HTML and JQuery
HTML:
<form class="form-group main-settings-form" id="main-settings-form-password">
<input class="form-control main-settings-form-input password-main" type="password" placeholder="Enter new password" id="new-password" pattern='(?=.*\d)(.{6,})' required>
<input class="form-control main-settings-form-input" type="password" placeholder="Retype new password" id="confirm-password" pattern='(?=.*\d)(.{6,})' required>
<div class="main-settings-form-buttons">
<button type="button" class="btn btn-danger settings-edit-cancel">Cancel</button>
<button class="btn btn-success" type="submit">Save</button>
<br>
<br>
Forgot password?
</div>
</form>
JS:
$(document).ready(function () { //This confirms if the 2 passwords match
$('#confirm-password').on('keyup', function (e) {
var pwd1 = $("#new-password").get(0);
var pwd2 = $("#confirm-password").get(0);
pwd2.setCustomValidity("");
if (pwd1 != pwd2) {
document.getElementById("confirm-password").setCustomValidity("The passwords don't match"); //The document.getElementById("cnfrm-pw") selects the id, not the value
}
else {
document.getElementById("confirm-password").setCustomValidity("");
//empty string means no validation error
}
e.preventDefault(); //would still work if this wasn't present
});
});
The problem is, the message is always triggered even if the passwords do match. Please help me trigger the message only when the passwords dont match, and be allowed to safely submit when they do.
JS fiddle: https://jsfiddle.net/kesh92/a8y9nkqa/
password requirements in the fiddle: 6 characters with atleast one number
jQuery get() returns the dom elements of each...they can never be equal
You want to compare values.
Try changing
if (pwd1 != pwd2) { //compare 2 dom nodes
To
if ( pwd1.value != pwd2.value) { //compare 2 dom node values
Note however that you also need to now consider empty values since you are over riding validty

clearing ng-messages in controller

I'm new to working with ng-message. I have an error message (form.$error below) showing up when I don't want it to, while a user is typing and changing their incorrect entry. how can I either a) use ng-focus properly or b) clear ng-messages in my controller when a user is typing? my attempt at a) using ng-focus is below but it isn't working. I also tried replacing ng-focus with ng-change but that still doesn't work. is it also possible to manually disable the error message from showing up in the controller by clearing ng-message?
my html. I attempt to set the form to valid when the user is typing.
<div class="col-xs-3">
<input ng-focus="setValid()"
class="form-control" required ng-blur="checkCodes()"
ng-model="code1">
</div>
further down in my html I have this other div where the error shows up when I don't want it to, when the user is typing.
<div ng-if="codeError"
ng-messages="form.$error">
<p ng-show="code1 === code2"
class="disabled-text long-error">Inputs can't be the same</p>
</div>
this is the main js in my controller:
$scope.checkCodes = function() {
if ($scope.code1 && $scope.code1 === $scope.code2) {
$scope.showUniqueError = true;
$scope.form.$setValidity("prop", false);
$scope.showError2 = false;
} else {
$scope.showUniqueError = false;
$scope.form.$setValidity("prop", true);
}
}
//tried to use this in ng-focus but not working.
$scope.setValid = function() {
$scope.form.$setValidity("prop", true);
}
You were pretty close you just had the wrong scope variable in your ng-if.
I also change the ng-blur attritbutes to ng-keyup. With ng-blur your error message would only be displayed if you click outside of the text box or another control gets focus.
In the live example you will see that if you type in the same value for each input box that your error will be displayed and if you change one of the input boxes to a different value then the error will be removed.
Live Example: http://codepen.io/larryjoelane/pen/QyOZNR
test html:
<div ng-app="test" ng-controller="testController"><!--begin app container-->
<div class="col-xs-3">
<input ng-focus="setValid()"
class="form-control" required ng-blur="checkCodes()"
ng-model="code1">
<input ng-focus="setValid()"
class="form-control" required ng-blur="checkCodes()"
ng-model="code2">
</div>
<div ng-if="showUniqueError"
ng-messages="form.$error">
<p ng-show="code1 === code2"
class="disabled-text long-error">Inputs can't be the same</p>
</div>
</div><!--end app container-->
Test Javascript(Unchanged other then adding module wrapper and closure):
(function(){
angular.module("test",[]).controller("testController",function($scope){
$scope.checkCodes = function() {
if ($scope.code1 && $scope.code1 === $scope.code2) {
$scope.showUniqueError = true;
$scope.form.$setValidity("prop", false);
$scope.showError2 = false;
} else {
$scope.showUniqueError = false;
$scope.form.$setValidity("prop", true);
}
}
//tried to use this in ng-focus but not working.
$scope.setValid = function() {
$scope.form.$setValidity("prop", true);
}
});//end controller
})();
You can do it without using ng-message.
<form class="form-signin hide" id="gbLoginForm" method="POST" name="loginform" ng-controller="LoginCtrl" novalidate>
<div class="form-group">
<label for="username">User Name</label>
<input type="text" class="form-control" id="username" name="email" placeholder="User name/email" ng-model="user.email" required autofocus>
<span class="has-error" ng-show="loginform.email.$dirty && loginform.email.$error.required">
<span class="help-block" ng-bind="getValue('EMPTYEMAIL')"></span>
</span>
<span class="has-error" ng-show="loginform.email.$dirty && !loginform.email.$error.required && loginform.email.$error.validemail">
<span class="help-block" ng-bind="getValue('INVALIDEMAIL')"></span>
</span>
</div></form>
// email field is empty
if(!$scope.user.email){
$scope.loginform.email.$dirty = true;
$scope.loginform.email.$setValidity('required', false);
return false;
}
//invalid email
if(!UtilityService.validateEmail($scope.user.email)) {
$scope.loginform.email.$dirty = true;
$scope.loginform.email.$setValidity('validemail', false);
return false;
}
You don't need use ng-blur or ng-keyup, because angular refresh your ngModel on change input.
To create the various checks can use directive use-form-error.
Live example jsfiddle.
<form name="ExampleForm">
<label>Code 1</label>
<input ng-model="code1" required/>
<label>Code 2</label>
<input ng-model="code2" required/>
<div use-form-error="isSame" use-error-expression="code1 && code1==code2" ng-show="ExampleForm.$error.isSame">Inputs can't be the same</div>
</form>

AngularJS - form validation, v 1.4.8

This is my first time using AngularJS, and the form validation is making me question my sanity. You would think this would be the easy part, but no matter how many ways I've tried Googling, the only thing that works is if I set a flag inside my controller's submit if the form is invalid to set the error class. I've looked at similar problems here, but none of them helped, so please do not simply dismiss this as a potential duplicate. Everything else has been a fail.
In the example mark up below I have reduced my form down to just one element. Here is what I have observed:
Using only $error.required does work. The ng-class { 'has-error' :registerForm.firstName.$error.required} does outline the text box with the bootstrap has-ertror class, but this is on form load, which I do not want.
The <p> element with the error message will exhibit the same behavior, so I know that the message exists and is not malfored. It will also display if I only use $error.required. But as soon as I add && registerForm.$submitted ( or $isdirty or !notpristine ) the message will not display on form submit. There are no errors (have developers tools open in chrome) and will post to the web API with no problem and return ok 200 or 400 if I send bad params.
I can write validation code inside my controller, checking if the field has a value and setting a flag on $scope such as $scope.firstNameIsRequired and that will work fine setting ng-show="$scope.firstNameIsRequired", but that will remove testability.
So the problem definitely has to be with how I am adding this in the markup. But after a weekend spent googling I am at my wits end. The only other thing different is that I am using a span on a click element to submit the form instead of an input = submit, but the registerForm.$valid function is setting the correct value. Do I somehow need to trigger the form validation in that ng-click directive?
I am using angular.js v 1.4.8.
I do have angular ui which has it's own validate, but that shouldn't interfere with the basic validation.
Here is the simplified markup:
<form name="registerForm" class="form-group form-group-sm"
ng-controller="userAccountController" novalidate>
<div class="form-group"
ng-class="{ 'has-error' : registerForm.firstName.$error.required }">
<div><label>First Name</label> </div>
<input type="text" class="form-control" id="firstName" name="firstName" value=""
ng-model="firstName" placeholder="First Name" maxlength="100" required=""/>
<p ng-show="registerForm.firstName.$error.required && registerForm.$submitted"
class="alert alert-danger">First Name is required</p>
</div>
<div>
<span class="btn btn-default"
ng-click="submit(registerForm.$valid)">Register</span>
</div>
My controller code is
angular.module( "Application" ).controller( "userAccountController", [
"$scope", "userAccountService", function ( $scope, userAccountService)
{
$scope.hasErrors = false;
$scope.errorMessages = "";
$scope.emailExists = true;
$scope.clearErrors = function (){
$scope.hasErrors = false;
}
$scope.onSuccess = function ( response ) {
alert( "succeeded" );
}
$scope.submit = function (isValid) {
if ($scope.registerForm.$invalid)
return;
alert("isvalid");
$scope.clearErrors();
var userProfile = $scope.createUser();
userAccountService.registerUser(userProfile, $scope.onSuccess, $scope.onError);
}
$scope.createUser = function () {
return {
FirstName: $scope.firstName, LastName: $scope.lastName, Email: $scope.email,
Password: $scope.password, SendAlerts: $scope.sendAlerts
};
};
}
]);
Any help will be appreciated. I probably just need a second set of eyes here because I have been dealing with this on and off since late Friday.
in angular you want use the element.$valid to check wheter an model is valid or not - and you use element.$error.{type} to check for a specific validation error.
Keep in mind that the form.$submitted will only be set if the form is actually submitted - and if it has validationerrors it will not be submitted (and thus that flag is still false)
If you want to show errors only on submit you could use a button with type="submit" and bind to ng-click event - and use that to set a flag that the form has been validated. And handling the submit if the form is valid.
A short example with 2 textboxes, having required and minlength validation:
angular.module("myApp", [])
.controller("myFormController", function($scope) {
$scope.isValidated = false;
$scope.submit = function(myForm) {
$scope.isValidated = true;
if(myForm.$valid) {
console.log("SUCCESS!!");
}
};
});
.form-group {
margin: 10px;
padding: 10px;
}
.form-group.has-error {
border: 1px solid red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>
<div ng-app="myApp" ng-controller="myFormController">
<form name="myForm">
<div class="form-group" ng-class="{'has-error': myForm.name.$invalid && isValidated}">
<span>Name:</span>
<input type="text" name="name" minlength="5" ng-model="name" required />
<span ng-if="myForm.name.$error.required && isValidated">Name is required</span>
<span ng-if="myForm.name.$error.minlength && isValidated">Length must be atleast 5 characters</span>
</div>
<div class="form-group" ng-class="{'has-error': myForm.email.$invalid && isValidated}">
<span>Email:</span>
<input type="text" name="email" minlength="5" ng-model="email" required />
<span ng-if="myForm.email.$error.required && isValidated">Email is required</span>
<span ng-if="myForm.email.$error.minlength && isValidated">Length must be atleast 5 characters</span>
</div>
<button type="submit" ng-click="submit(myForm)">Submit</button>
</form>
</div>

Categories