I'm looking for a way to use a single parsley validation error message for a set of input fields. The primary example of this would be for an address input field, but I'm sure others can come up with similar examples where this might be useful.
<div id="error-container"></div>
<input name='address1' data-parsley-maxlength="255" data-parsley-errors-container="#error-container">
<input name='address2' data-parsley-maxlength="255" data-parsley-errors-container="#error-container">
<input name='address3' data-parsley-maxlength="255" data-parsley-errors-container="#error-container">
Using the above code right now would result in 3 different error messages, but I want to set up a scenario where only one message would be displayed if any of the inputs are invalid.
Thanks in advance
Update
After a bit of JS console fun, I think I've found something that works. The idea below is to prevent any UI changes being done by parsley on the group, and to trigger a check on the whole group each time one of the elements are validated. This may not be the best way to do things, but it appears to be working with my single test-case. I'm thinking that this could be re-worked into a validator so that I can re-use it for other sets of inputs in the future.
<div id="error-container"></div>
<input name='address1' data-parsley-ui-enabled='false' data-parsley-trigger='change' data-parsley-group='address-grp' data-parsley-maxlength="255" data-parsley-errors-container="#error-container">
<input name='address2' data-parsley-ui-enabled='false' data-parsley-trigger='change' data-parsley-group='address-grp' data-parsley-maxlength="255" data-parsley-errors-container="#error-container">
<input name='address3' data-parsley-ui-enabled='false' data-parsley-trigger='change' data-parsley-group='address-grp' data-parsley-maxlength="255" data-parsley-errors-container="#error-container">
var $addressFields = $("[data-parsley-group='address-grp']");
addressFields.each(function(index, element) {
$(element).parsley().on('field:validated', function(parsleyField) {
var fieldOptions = parsleyField.actualizeOptions().options;
var classHandler = fieldOptions.classHandler(parsleyField);
var container = $(fieldOptions.errorsContainer);
classHandler.removeClass(fieldOptions.successClass);
classHandler.removeClass(fieldOptions.errorClass);
var valid = parsleyField.parent.isValid(fieldOptions.group);
if(valid) {
console.log("Valid");
classHandler.addClass(fieldOptions.successClass);
container.html("");
} else {
console.log("Invalid");
classHandler.addClass(fieldOptions.errorClass);
container.html("Error");
}
});
});
You can do this fairly cleverly with a bit of CSS if you add a particular class to your error container.
HTML:
<div id="error-container" class="parsely-single-error"></div>
CSS:
.parsely-single-error .filled ~ .filled {
display: none;
}
Explanation
The CSS reads, "hides any child elements of the error-container that have the class 'filled' and come after another element that has the class 'filled'". This has the effect of hiding all but the first 'filled' error in the error container.
For reference, the parsely error container looks like this when filled:
<div class="parsely-single-error" id="error_container">
<span class="help-block filled" id="parsley-id-5">
<div class="parsley-required">This value is required.</div>
</span>
<span class="help-block" id="parsley-id-7"></span>
<span class="help-block filled" id="parsley-id-9">
<div class="parsley-required">This value is required.</div>
</span>
<span class="help-block filled" id="parsley-id-11">
<div class="parsley-required">This value is required.</div>
</span>
<span class="help-block" id="parsley-id-13"></span>
</div>
I'm not sure there a great way to do this.
You could try configuring it so that errors are put in the same container, and then use CSS to only show the :first of them?
Related
I m trying to add angularJs event to a button if value of input field changes. But i cannot find a solution how can i do it. I know how to detect change but do not know how to add a new event using controller.
Let me illustrate by example:
<form name="addNewCourse">
<input ng-model="courseNameEdit" ng-value="courseName" ng-pattern="regex" ng-trim="false" name="addNewCourseField" ng-minlength="5" ng-maxlength="60" required>
<div ng-messages="addNewCourse.addNewCourseField.$error" style="text-align: left !important; color:red;">
<div ng-message="required">This field is required*</div>
<div ng-message="pattern">Must be only digits or numbers</div>
<div ng-message="maxlength">Must not exceed 60 characters</div>
<div ng-message="minlength">Must not be smaller than 5 characters</div>
</div>
<button class="btn btn-primary" ng-click="saveCourseNameFunc(courseNameEdit)">Save</button>
</form>
what i want is to add ng-disabled="addNewCourse.$invalid" into the button if value change using controller. Thanks in Advance.
If I'm not wrong here, You are about to validate your form while field value changes via the controller. Try below solution and let me know if this will not work for you.
FORMOBJECT.$setSubmitted();
You can also try triggering change event of that field via controller like:
angular.element('#INPUT_ID').trigger('change');
Hope you will get the solution from one of the given above.
How about using ng-change and a boolean in your ng-disabled expression activate the disability simply.
<form name="addNewCourse">
<input ng-change="changed()" ng-disabled="addNewCourse.$invalid && activeDisable" ng-model="courseNameEdit" ng-value="courseName" ng-pattern="regex" ng-trim="false" name="addNewCourseField" ng-minlength="5" ng-maxlength="60" required>
<div ng-messages="addNewCourse.addNewCourseField.$error" style="text-align: left !important; color:red;">
<div ng-message="required">This field is required*</div>
<div ng-message="pattern">Must be only digits or numbers</div>
<div ng-message="maxlength">Must not exceed 60 characters</div>
<div ng-message="minlength">Must not be smaller than 5 characters</div>
</div>
<button class="btn btn-primary" ng-click="saveCourseNameFunc(courseNameEdit)">Save</button>
</form>
and your controller must contain something like this:
$scope.activeDisable = false;
$scope.change = function(){
$scope.activeDisable = true;
}
I currently has a simple form that I am trying to test with Protractor. While it seems to work fine with basic input types, it does not seem to work with ngTagsInput the way I have it set up. I was wondering if there was a particular way of setting this up without triggering the error below.
Failed: unknown error: cannot focus element
(Session info: ...)
(Driver info: ...)
...
Currently my form, has 4 elements. A name (standard input), a type (radio buttons), targets (the tag inputs), and a submit button. In HTML, it appears something like this.
<div class="form-group">
<input class="form-control" placeholder="Enter name here..." ng-model="name">
</div>
<div class="form-group">
<div id="t1" class="radio">
<input name="radioType" id="a" value="A" checked="" type="radio" ng-model="type">
</div>
<div id="t2" class="radio">
<input name="radioType" id="b" value="B" type="radio" ng-model="type">
</div>
<div id="t3" class="radio">
<input name="radioType" id="c" value="C" type="radio" ng-model="type">
</div>
</div>
<div class="form-group">
<tags-input class="btags" name="targets" min-length=1 placeholder="Enter your targets here..." min-tags=1 add-on-blur="true" ng-model="targets">
</div>
<div class="form-group">
<button id="submit" type="button" class="btn btn-primary" ng-click="submitThing()"></button>
</div>
Lastly, the one Protractor test I have written looks like this.
it('should submit a valid thing',function(){
//Sets a name for the object
element(by.model('name')).sendKeys('user');
//Sets a type for the object
element(by.id('t1')).click();
/*Inputting tags (the functions below) seem to not work and throw an error*/
//Clicks (or focuses on) the tag input box
element(by.model('targets')).click();
//Types in the elements within it
element(by.model('targets')).sendKeys('target1');
//Presses Enter to submit that particular target
browser.actions().sendKeys(protractor.Key.ENTER).perform();
//Repeat for more
element(by.model('targets')).sendKeys('target2');
browser.actions().sendKeys(protractor.Key.ENTER).perform();
element(by.model('targets')).sendKeys('target3');
browser.actions().sendKeys(protractor.Key.ENTER).perform();
element(by.id('submit')).click();
}
The managed to find a solution thanks to MBielski's comment. It turns out that you need to look at the HTML that is rendered and focus on one of those elements since it is a custom element. Using Google Chrome's developer tools, I managed to find some of the inner code for the make up of the tags. In short, it appears as:
<input class="input" ng-model="newTag.text">
There is much more information in this inner element, but I left what was relevant. So, you add information into the tags inbox I've defined in the question asked, you would simply focus on the model called "newTag.text", like this.
it('should submit a valid thing',function(){
//Sets a name for the object
element(by.model('name')).sendKeys('user');
//Sets a type for the object
element(by.id('t1')).click();
//Clicks (or focuses on) the tag input box // This may not be needed
element(by.model('newTag.text')).click();
//Types in the elements within it
element(by.model('newTag.text')).sendKeys('target1');
//Presses Enter to submit that particular target
browser.actions().sendKeys(protractor.Key.ENTER).perform();
//Repeat for more
element(by.model('newTag.text')).sendKeys('target2');
browser.actions().sendKeys(protractor.Key.ENTER).perform();
element(by.model('newTag.text')).sendKeys('target3');
browser.actions().sendKeys(protractor.Key.ENTER).perform();
element(by.id('submit')).click();
}
This solved the problem for me. Hopefully it also does for others.
Bit of a trivial one here however am new to Angular so excuse me.
Whenever I have an input field - I only want an action to occur if the field actually contains some valid content.
What i find I'm having to do is first instantiate a variable, then assign that to whatever input there is then do a boolean check in a if.
Is the the correct way to go around this? If i don't instantiate the variable (or don't use one at all) i run into getting undefined error:
var textToSearch = '';
textToSearch = $scope.main.searchInputField.trim();
if (textToSearch){
$location.path('/search/'+textToSearch);
}
Also (on another note)
I'm sanitising everything on the server side however on Angular/client side is there a quick and easy function I can use?
Thanks
I suppose you have an ng-model for 'main.searchInputField' so if you want to check if the field is empty you can just write
$scope.main = {};
if($scope.main.searchInputField.trim().length > 0){
//do stuff
}
suppose you have ng-model of input field 1 as some.data and input field 2 as some.data1
for(var i=0; i<$scope.some.length;i++){
if($scope.some[i]){
//do something
}
}
it will check every field.
This is using Bootstrap for email validation, but the same logic applies if you are using your own classes.
<div ng-class="(emailRegExp.test(email) && email != null) ? 'has-success' : 'has-error'" class="form-group has-feedback">
<div class="input-group">
<div class="input-group-addon">
<span class="glyphicon glyphicon-envelope"></span>
</div>
<input ng-model="email" ng-change="checkEnableSubmit()" id="email" placeholder="Email Address" type="text" class="form-control" aria-describedby="emailStatus">
</div>
<span ng-class="(emailRegExp.test(email) && email != null) ? 'glyphicon-ok' : 'glyphicon-remove'" class="glyphicon form-control-feedback" aria-hidden="true"></span>
</div>
The ng-class directive accomplishes the validation if:
The checkEnableSubmit() function in your controller only allows a submission when the data is valid (I would be happy to include that code, too)
Both classes in the ternary operator on line #1 indicate valid data and non-valid data (in this example one makes the input appear green and the other red)
I am trying to validate textAngular fileds, I need to add required, max and min characters and border color on red/green on textAngular... I have for each loop and inide textAngulars...
Here is my code:
<form ng-submit="addReply(x)" class="dd animated slideInDown" novalidate>
<div class="form-group">
<text-angular ng-minlength=10 ng-maxlength=600 required ta-text-editor-class="form-control myform1-height" ta-html-editor-class="form-control myform1-height" ta-toolbar="[['bold','italics']]" style="min-height: 100px; color:red;" ng-model="form.reply[x.pivot.comment_id]"></text-angular>
<span ng-show="form.reply[x.pivot.comment_id].$dirty && form.reply[x.pivot.comment_id].$invalid"></span>
<span ng-show="form.reply[x.pivot.comment_id].$error.min || form.reply[x.pivot.comment_id].$error.max">
The value must be in range 0 to 10!</span>
<span ng-show="form.reply[x.pivot.comment_id].$error.required">Email is required.</span>
</div>
<div class="form-group">
<addreply></addreply>
</div>
</form>
My code don't work I don't know why...
According to AngularJS documentation, your form and inputs should have names.
Then you should set validation ng-show's to form_name.input_name.$error and so on, like here
this one is a small example based on your question for
validating the required field
http://plnkr.co/edit/6PTNg3atPHAjL0XFtvWj?p=info
I am able to validate my AngularStrap datetimepicker, but I cannot differentiate between a required validation failure and an invalid date failure. The only error that ever shows on screen is the required error, whether it is required or an invalid string. Is it possible in cases where a string has been entered that is invalid to show a different validation message? Here is my code :
<div class="control-group" ng-class="{error: form.BirthDate.$invalid}">
<label class="control-label" for="BirthDate">{{'_BirthDate_' | i18n}}</label>
<div class="controls">
<input id="BirthDate" name="BirthDate" title="BirthDate" type="text" ng-model="user.BirthDate" data-date-format="dd/mm/yyyy" bs-datepicker required>
<span ng-show="form.BirthDate.$dirty && form.BirthDate.$error.required">{{'_BirthDateRequired_' | i18n}}</span>
<!--<span ng-show="form.BirthDate.$dirty && form.BirthDate.$error.pattern">{{'_BirthDateInvalid_' | i18n}}</span>-->
</div>
</div>
What I want is something similar to the ng-pattern check but specific to the datetimepicker.
first of all, I think this has no real link with the date picker or not, if I understand your problem, you are trying to display different messages according to the error that lead to the $invalid for the form
If it's the case, the code you provided will only show a message when the date is invalid (but only because you commented the part for the pattern ;) )
I was super lazy while testing, so I didn't use the datepicker, you'll have to enter a date manually, but I did this fiddle : http://jsfiddle.net/DotDotDot/ELf5A/2/
As I didn't know exactly in what context you were using it, I used different methods to display validation error messages
The HTML part is simple. There is a form, two fields required, one with a pattern check for the date, the other only for the required validation. I added 2 error messages for the date, one displayed when the form hasn't been touched, telling you what format is expected, the other only shows up when the pattern is wrong.
You can click on the button to check the whole validation and then show another message, which will tell you if the form is valid or not, and if not, if it's because of the pattern of the date.
<div ng-controller='theCtrl'>
<form name='theForm'>
Enter something here : <input type='text' ng-model='someField' name='someField' required /> <br/>
Enter a date here : <input type='text' ng-model='theDate' name='theDate' ng-pattern='datePattern' required />
<span ng-show='theForm.theDate.$error.pattern'>Your date format is invalid, please check it again</span>
<span ng-show='theForm.theDate.$pristine'>Enter a valid date here : DD/MM/YYYY</span>
<br/> <input type='button' ng-click='validation(theForm)' value='Try to validate me!' />
<br /> {{errorMsg}}
</form>
</div>
The JS part is not very complicated either. When you click on the button, the form is being sent to the validation function, which will actually do all the checks you want, I only did the one corresponding to the pattern, but you could totally check whatever you want about the validation
$scope.validation=function(aForm){
//console.log(aForm)
if(aForm.theDate.$error.pattern)
$scope.errorMsg='The pattern you entered isn\'t good enough, try again !'
else{
if(aForm.$invalid)
$scope.errorMsg='Something is invalid, please check all the fields !'
else//valid
{
$scope.errorMsg='Not bad !'
alert("good job !")
//maybe you can also submit this form here ;)
}
}
}
This validation function could totally be used as the trigger in a ng-show/ng-hide too, this is why I also added another function :
$scope.whatToDisplay=function(aForm){
if(aForm.$valid)
return 'valid';
if(aForm.theDate.$error.pattern)
return 'date';
if (aForm.$invalid)
return 'notdate';
}
This will return a string corresponding to what is happening during the validation, which will be handled with ng-show :
<span ng-show='whatToDisplay(theForm)=="date"'>Displayed if the date is wrong</span>
<span ng-show='whatToDisplay(theForm)=="notdate"'>This is displayed if the form is invalid, but not because of the date format</span>
<span ng-show='whatToDisplay(theForm)=="valid"'>Displayed if the form is valid</span>
To summarize a bit, you can use 4 different methods
A validation function triggered with a click (useful for submit buttons), corresponding to the validation() function in my fiddle
A function associated with some ng-show, which will automatically watch every change, like the whatToDisplay() function
The ng-show associated with only the form attributes, like what you were doing with your code
The class automatically applied to the form ( I didn't explain it, but you can see it in the fiddle, the border change if the pattern is wrong or if it's only invalid )
Sorry, I had some difficulties to make this short, I let you play with the code, it's easier to understand that way, I hope this will help you
You should use ngMessages in AngularJS 1.3 to do the error messaging with less code and complexity. The bs-angular directive creates a message for the "date" string value of ng-message in your list of messages.
<div class="control-group" ng-class="{error: form.BirthDate.$invalid}">
<label class="control-label" for="BirthDate">
{{'_BirthDate_' | i18n}}
</label>
<div class="controls">
<input id="BirthDate" name="BirthDate" title="BirthDate" type="text"
ng-model="user.BirthDate" data-date-format="dd/mm/yyyy"
bs-datepicker required>
<span ng-show="form.BirthDate.$dirty && form.BirthDate.$error.required">{{'_BirthDateRequired_' | i18n}}</span>
</div>
<div class='alert alert-danger' ng-messages='myForm.BirthDate.$error'
ng-if='!myForm.BirthDate.$valid'>
<div ng-message="date">Please enter a valid date</div>
<div ng-message="required">Birthdate is required</div>
</div>
</div>
This code helps to show the invalid datetime error message
$scope.date=='Invalid Date'
{
err('Your error message');
}