Is it possible to show a Validation Summary, a Div on top of the page with all the Validation error messages in angularjs , on form submit ?
I am coming from a .Net background and used to have a validation summary concept,all the examples i have seen in angular shows the error message right next to the control.
I am very new to angularjs , so an example or pointer to the right direction would be appreciated !
Thanks !
Yeah, you can use flags on each of your input fields, which will show a specific error message based on whether that flag is true or false.
For example:
<div ng-controller="signupCtrl">
<input type="text" id="username">
<input type="text" id="password">
<button ng-click="validate()">Sign-up</button>
</div>
Then, the validate function would run several other functions that would set flags. For example:
function signupCtrl($scope) {
$scope.validate = function() {
if( /* username is bad */ ) {
$scope.usernameError = true;
} else if ( /* password is bad */ ) {
$scope.passwordError = true;
} else {
// AJAX call to submit sign-up, or whatever
}
}
}
Your error messages would look like this:
<div class="error" ng-show="usernameError">Your username is bad</div>
<div class="error" ng-show="passwordError">Your password is bad</div>
Or, better yet, you can use a model, and only one error message:
<div class="error" ng-show="error">You {{field}} is bad</div>
But that second option would require some different tweaking of your code.
Related
My form have two buttons say "Draft" and "Submit", so for draft some validations are applicable and same for submit button. I have one variable cmpnStatus it is initialised with value 1. For draft value of cpmnStatus is 0 and for submit it is 1.
<div class="form-group">
<label>Short Description<span class="red-ast">*</span></label><br/>
<textarea ng-model="shortdesc" ng-change="shortchange(shortdesc)" class="form-control b-rad3" ng-required="cmpnStatus == 0"></textarea>
</div>
<button type="submit" ng-click="campform.$valid && submitDraft(campform)" class="btn btn-draft">Save as draft</button>
<button type="submit" class="btn btn-launch" ng-click="campform.$valid && submitCampaign()">Submit for Approval</button>
Below is the code of submitDraft function.
$scope.submitDraft = function(form){
$scope.cmpnStatus = 0;
if(form.$valid) {
alert("valid");
} else {
alert("invalid");
}
//Then call to save data in db
};
My problem is when I click on draft form shows valid and save data in db and after that it points the required validation because initially value of cpmnStatus is 1 and according to condition required validation condition fails. Again I click on draft button now required validation is working fine because value of cpmnStatus changes from 1 to 0. I want that when user click on draft button and when the value of cpmnStatus changes it should be show me required validation (even in first click) according to condition(ng-required="cmpnStatus == 0"). Is there any other way to do the same ?
1st change the html to be like this :
<button type="submit" ng-disabled="campform.$error" ng-click="submitDraft(campform)" class="btn btn-draft">Save as draft</button>
<button type="submit" class="btn btn-launch" ng-disabled="campform.$error" ng-click="submitCampaign()">Submit for Approval</button>
Disabling button for user when form is invalid is better.
About the cmpnStatusThings i suggest you to use a checkbox or radio button to switch between draft or approval mode :
<input type="checkbox" ng-model="cmpnStatus" ng-true-value="1" ng-false-value="0"/>
Radio sample :
<input type="radio" ng-model="cmpnStatus" ng-value="1"/>
<input type="radio" ng-model="cmpnStatus" ng-value="0" />
Thank you for the clarification. Here is a function I am currently using:
$scope.checkIfSaveAllowed = function() {
var timer = setTimeout(function() {
var validControls = document.getElementsByClassName('has-feedback ng-scope has-success');
var modalSaveBtn = document.getElementById('eventModalSaveBtn');
if (validControls.length >= 3) {
if (validControls.length == 4) {
modalSaveBtn.disabled = false;
}
else if (validControls[0].id != "commentFormGroup" && validControls[1].id != "commentFormGroup" && validControls[2].id != "commentFormGroup") {
modalSaveBtn.disabled = false;
}
}
else {
modalSaveBtn.disabled = true;
}
}, 50);
}
I call this function on every field in the form using an ng-change. That else if in the middle is how I accomplish what you are asking about. The commentFormGroup is not required in my code. I check if (1) there are only three valid fields and (2) none of those valid fields are the optional field, then the button should be enabled.
In your case, you could have two functions called by the ng-change, one for each button or you could specify when one should be disabled and the other enabled.
Alternatively, you could display a customized error message instead of disabling the button. I hope this helps.
I'm trying to figure out how to make parsleyjs only trigger validation on blur for a field that has already failed validation.
See http://jsfiddle.net/billyroebuck/zbmv2d3w/
Markup:
<form id="myform">
<label for="email">Email</label>
<input type="email" name="email"
data-parsley-required="true"
data-parsley-type="email"
data-parsley-custom
data-parsley-trigger="blur"
/>
<input type="submit" />
</form>
JavaScript:
window.Parsley.addValidator('custom',
function (value, requirement) {
console.log('custom validation triggered');
sleepFor(3000); // simulate a delay (testing only)
if (value == 'test#test.com') {
console.log('custom validation failed');
return false;
}
console.log('custom validation passed');
return true;
}, 32)
.addMessage('en', 'custom', 'custom validation failed');
$('#myform').parsley();
function sleepFor(sleepDuration) {
console.log('pretend this takes a while...');
var now = new Date().getTime();
while (new Date().getTime() < now + sleepDuration) { /* do nothing */
}
}
parsleyjs Version 2.2.0-rc1
The email field has validation rules to check:
a value is provided,
the value entered is a valid email address,
some custom rule (pretend this is an AJAX request)
I have the parsley-trigger attribute for this field set to blur.
Steps:
Open the console
Enter "a#b.com" in the email field above and press tab
Note the custom validation is triggered (good)
Enter "xyz" in the email field and press tab
Note the parsley type validation kicks in (good)
Enter "xyz#test.com" in the email field View the console
Note the custom validation is triggered the moment the input becomes a
valid email (in this case when you press the letter c in .com) vs
blur :(
How can I make sure the validation is only triggered on the blur event for invalid fields?
Thanks in advance!
I'm afraid there is no such option currently. The idea is to remove the error message as soon as possible and everyone appears to like this.
I am using latest version of angular.js and WebAPI & bootstrap.
Imagine a form with few textboxes & submit button. Once a user submits the form, data is validated by WebAPI call on server as we cant trust client side validations.
In API controller, we do all our business validations.
Assuming that data entered in all the textboxes are invalid:
How should i return error message from my WebAPI so that the form displays it properly ?
In normal MVC way without angular, this is easy. We can add errors to ModelState and the view will pick it and show the errors properly.
AngularJS has built in form validation:
WebApi
You can return errors in whatever format you want. I would recommend that the response should contain following information:
An error message describing the error
In which part of the request the error occured (Payload, url params, query params)
Which attribute triggered the error (email, password, ...)
The response should also have the correct error status code (400, 401, ...)
Client
Assume that your response looks like this:
{
"message": "Email is invalid",
"area": "payload",
"field": "email"
}
Create your form and make sure the name attribute is assigned, since in your form validation you will need the it. By now angular will append form validations states to your elements:
<input type="email" name="email" id="email" ng-model="user.email" ng-minlength="6" required />
You can now dynamically display error messages by accessing the validation fields:
<span ng-show="form.email.$error.required && form.email.$dirty">Email can not be empty</span>
The angular way is using form with the angular directive ng-valid. you can simply add it e.g. to your input:
<input type="text" ng-valid="myFunc()">
You can define myFunc() within your scope, do whatever you like and return a boolean value.
Now, just add ng-disabled to your submit button and bind it to angular's form $valid property:
<button type="submit" ng-disabled="!myForm.$valid">Cool Button</button>
Note: myForm is the name of your form.
Further information in the docs.
The solution for me was : https://stackoverflow.com/a/23087715/3290276
Just i needed to change two things 1)Get data and 2)low case the property modelState.
parseErrors(response.data)
function parseErrors(response) {
var errors = [];
for (var key in response.modelState) {
for (var i = 0; i < response.modelState[key].length; i++) {
errors.push(response.modelState[key][i]);
}
}
return errors;
}
here is my first question on this awesome forum.
my need is to warn the user why the number he enters is invalid, but I want to print only one message at each time. I've implemented a solution but it's not really easily evolutive.
Here is my HTML code :
<input type="number" name="amountReceived" class="styled" data-ng-model="cashAmountReceived" required>
<div class="error" data-ng-show="cashPaymentForm.amountReceived.$error.required && cashPaymentForm.submitted">Valid amount required</div>
<div class="error" data-ng-show="cashPaymentForm.amountReceived.$error.notEnought && cashPaymentForm.submitted">It's not enought</div>
<div class="error" data-ng-show="cashPaymentForm.amountReceived.$error.negatif && cashPaymentForm.submitted">Positive value only</div>
and here is my Controller code :
$scope.$watch('cashAmountReceived', function() {
if(angular.isNumber($scope.cashAmountReceived)){
var tmp = $scope.cashAmountReceived.toString();
tmp = tmp.replace(/(\d{0,9})+\.(\d{0,2}).*/,'$1.$2');
$scope.cashAmountReceived = parseFloat(tmp);
if( $scope.cashAmountReceived < 0){
$scope.cashPaymentForm.amountReceived.$setValidity('negatif', false);
$scope.cashPaymentForm.amountReceived.$setValidity('notEnought', true);
}
else{
$scope.cashPaymentForm.amountReceived.$setValidity('negatif', true);
if($scope.cashAmountReceived < $scope.totalProductPrice){
$scope.cashPaymentForm.amountReceived.$setValidity('notEnought', false);
}
else{
$scope.cashPaymentForm.amountReceived.$setValidity('notEnought', true);
}
}
}
else{
$scope.cashPaymentForm.amountReceived.$setValidity('notEnought', true);
$scope.cashPaymentForm.amountReceived.$setValidity('negatif', true);
}
});
I've to manually manage validity errors to make sure that only one will be printed thanks to the ng-show directives in my HTML page. I'd like to implement a easily evolutive solution, in case I need to add more validation criteria.
I think about to make my own directive with a priority management system on my custom errors and compatible with the defaults errors possibilities, but I don't know how to proceed.
Or maybe I can leave the process in the controller and create only one custom error called custom and define a scope variable called errorReason whitch will contain the appropriate warning message
I'll have something like that in my HTML code :
<input type="number" name="amountReceived" class="styled" data-ng-model="cashAmountReceived" required>
<div class="error" data-ng-show="cashPaymentForm.amountReceived.$error.custom && cashPaymentForm.submitted">{{errorReason}}</div>
What do you guys think about it?
I apologize if my english is not correct.
In my form validation there is part of server validations.
So I should get back from the server list with the names of the fields and a string with the error in each of them.
My idea was to write a general code knowledge to deal with all fields without knowing them in advance, by accessing them with their name.
this is field for example:
<!-- Email -->
<div class="form-group" data-ng-class="{ 'has-error' : step1Form.email.$invalid && (!step1Form.email.$pristine || submitted) }">
<label>Email</label>
<input type="email" name="email" class="form-control" data-ng-model="user.email" required data-ng-minlength="5" data-ng-maxlength="60">
<p data-ng-show="step1Form.email.$error.required && (!step1Form.email.$pristine || submitted)" class="help-block">required!</p>
<p data-ng-show="step1Form.email.$error.minlength" class="help-block">too short1</p>
<p data-ng-show="step1Form.email.$error.maxlength" class="help-block">too long!</p>
<p data-ng-show="step1Form.email.$error.email" class="help-block">invalid email!</p>
<p data-ng-show="step1Form.email.$error.serverError" class="help-block">{{emailServerError}}</p>
</div>
like you can see, the variable emailServerError is saved for errors that come from the server validations...
i have a lot fields in my application and i try to write generic code that will fit for all the fields...
so this is the angular code:
// function to submit the form after all validation has occurred
$scope.submitForm = function() {
// check to make sure the form is completely valid
if ($scope.step1Form.$valid) {
// now we will go to server side validation
// AJAX calls.......
// lets say we got this back:
var problem = { field: 'email', msg: 'this email is already registered'};
// now we need to setValidity for email input.
var errorVariableName = $parse(problem.field + 'ServerError'); // Get the name of the error string variable.
errorVariableName.assign($scope, problem.msg); // Assigns a value to it
console.log($scope.emailServerError); // = 'this email is already registered'
// HERE THE PROBLEM:
// now i need to do something like that:
// $scope.step1Form. + problem.field + .$setValidity('serverError', false);
// but i dont know how to this that.
// i think that i need to get this element ($scope.step1Form. + problem.field) in some way by name, and then use setValidity on it. but i dont know how..
}
};
the question is in the comments inside the code...
You can try
$scope.step1Form
and then access the right value with
$scope.step1Form["nameOfProblemfield"]