Deletion Error with Email Validation in Angular - angularjs

So I've recently taken over an Angular Giving Form Application. I am running validation on the email field using ng-pattern and displaying the errors on blur with ngMessages. The validation works great, however once the validation passes as $valid if the user decides they need to make a change in their email and begin to delete part of the first deletion deletes the last character of the email as expected, but the second deletion deletes the entire field forcing the user to start from scratch.
The regex for ng-pattern is being set in the controller scope with the variable $scope.emailre
The files are much to large to place here but here is the link to the site I am working on for my client.
https://epiqa.moodyglobal.org/corporate/
Snippet of Angular controller:
myApp.controller('mainCtrl', function($scope, localStorageService, $http) {
$scope.emailre = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
Snippet of HTML Form:
<div class="row form-group">
<div class="col-sm-6">
<div>
<label class="label" for="txt_donorEmail">E-mail:</label>
<input ng-class="{ 'submitted-error' : givingForm.email.$invalid && submitted }" ng-model="email" type="text" id="email" name="email" class="textbox required full form-control" maxlength="50" ng-pattern="emailre" required />
</div>
<div ng-messages="givingForm.email.$error" ng-if="givingForm.email.$touched || submitted">
<div class="errorText" ng-message="required">This field is required</div>
<div class="errorText" ng-message="pattern">Enter a valid email</div>
</div>
</div>
</div>
I have tried changing the input type from type="text" to type="email" but when doing that any time the user types two (.) periods the field gets immediately deleted.
Please help any ideas are very welcome.

The behavior is caused by this section
$scope.$watch('email', function(value){
localStorageService.set('email',value);
$scope.emailValue = localStorageService.get('email');
});
By Angular documentation
The default behaviour in ngModel is that the model value is set to undefined when the validation determines that the value is invalid. By setting the allowInvalid property to true, the model will still be updated even if the value is invalid.
I'm not sure whether you want to save the invalid email into localStorage, though. Maybe you can add a check only update when the value is valid.

Related

Angular js ng messages show error on init

In my project I have angularjs 1.5.10 and ng-messages 1.5.10. I use it in simple form:
<form class="form-horizontal" ng-submit="createBooking()" role="form" name="createBookingForm" novalidate>
<div class="form-group">
<label for="payment_details_last_name" class="col-sm-3 control-label">Last name</label>
<div class="col-sm-6">
<input type="text"
id="payment_details_last_name"
name="payment_details_last_name"
class="form-control"
ng-model="payment_details.last_name"
ng-required="true"
ng-maxlength="30" />
<div ng-messages="createBookingForm.payment_details_last_name.$error" role="alert">
<div ng-message="required">This field is required</div>
<div ng-message="maxlength">Your field is too long</div>
</div>
</div>
<div class="col-sm-3"></div>
</div>
</form>
In controller:
$scope.members = [{
'first_name': '',
'last_name': '',
'email': '',
'phone_number': '',
'date_of_birth': '',
}];
And on initial I always see error This field is required. I tried to create empty object in controller:
$scope.createBookingForm = {};
I also show form after initialized <div ng-if="initialized">
Nothing is working. Project using angular-seed skeleton
I saw dirty hacks like if $touched else, but I want to understand what is wrong...
Nothing is wrong about it, check out the sample in the official guide. They have required error shown by default. It seems wrong for the first glance, but this is the only correct way to handle such a case.
So basically, ng-messages does exactly what docs says:
ngMessages is a directive that is designed to show and hide messages
based on the state of a key/value object that it listens on.
the directive works in a real time and shows errors for current input state, that makes sense.
So if you want no messages to be shown by default, you should use some of approaches, discussed hundred of times
How to make ngMessage for required fields only show when dirty or submitting a form?
Angular : ng-message validation on submit click
AngularJS: Hiding ng-message until hitting the form-submit button
AngularJS 1.5.6 reset form & ng-messages
If you need some other improved behavior - there is no quick solution at the moment, you have to come up with your own validation engine that fit your needs.

Angular validation (can't reach controller if required fields are empty)

I'm trying to implement validation for a form using Angular 1.1.1 and Ionic.
There are many "wallets" and the user needs to send a new "value" to each of the wallet. There's also a specified previous value of the wallet. The validation should check if all the input field are filled out and if the new value is bigger than previous.
My form (index.html):
<form name="myForm" ng-submit="sendValues(wallets)" ng-controller="valuesCtrl">
<div class="row" ng-repeat="wallet in wallets">
<div class="col item item-input-inset">
<label class="item-input-wrapper item-text-wrap">
<input name="wallet_{{wallet.id}}" type="number" ng-model="wallet.value" type="text" required/>
</label>
<span ng-show="myForm.wallet_{{item.id}}.$error.required">!!!</span>
</div>
<div class="col item">{{ wallet.previous }}</div>
</div>
<button class="button" type="submit">Submit</button>
</form>
It results in always showing "!!!" error for empty input even if the user haven't already submitted the form. I tried to use $scope.myForm.submitted=true; in the controller but the problem is it reaches the controller only if all the fields are filled out.
My controller (values.js):
'Use Strict';
angular.module('App')
.controller('valuesCtrl', function($scope, $localStorage, UserService, $state) {
$scope.sendValues = function(wallets){
debugger;
...
})
Can anyone help me to figure out why I can't see the debugger window if not all the fields are with info?
Can you suggest how to make a custom validation? (new value should be bigger than previous)
It results in always showing "!!!" error for empty input even if the user haven't already submitted the form?
Your ng-show should be
ng-show="myForm.$submitted==true && myForm.wallet_{{item.id}}.$error.required"
and form should be have novalidate attribute if you want custom validation
<form name="myForm" ng-submit="sendValues(wallets)" novalidate>
otherwise it will do default html validation
I tried to use $scope.myForm.submitted=true; in the controller but the problem is it reaches the controller only if all the fields are filled out
Its because ng-submit will validate for true condition($valid==true) for every form control element .
If it is filled and valid data then only form $valid flag is set to true otherwise not.In case $valid==true,you will able to submit the form and function in controller get fired
you can use
<input type="submit" ng-click="sendValues(wallets)" value="Save" />
if you want to submit the form without validation and want to do validation in controller
You can read more from angular#form

Have AngularJs update {{binding}} as the user types in input[email]

Angular only updates the model from an input[email] after the user has entered a valid email address. How can I add a {{binding}} somewhere on the page that will update with the email value as the user types -- even before the user has typed in a valid email address?
Here's what I've tried so far:
<div ng-app>
<div ng-controller="MyCtrl">
<form name="MyForm" novalidate>
Name: <input type="text" name="name" ng-model="contact.name" /><br/>
Name as you type: {{contact.name}}<br/>
Email: <input type="email" name="email" ng-model="contact.email" /><br/>
Email as you type: {{contact.email}} (doesn't work)<br/>
Also doesn't work: {{$document.forms.MyForm.elements.email.value}}
</form>
</div>
</div>
Controller:
function MyCtrl($scope) {
$scope.contact = {};
}
(fiddle)
The name updates in real-time like I want, but the email doesn't.
I'd like to leave the email validation enabled. I just need some way to bind the un-validated input[email] text, so it updates as the user types.
Update 2014/7/8
I'd like to add an explicit requirement that the type="email" remains unchanged. I do not want to change the semantics of the markup to workaround a limitation of the framework. If need be, I'd rather pull in a complementary dependency (such as jQuery) to shim in the needed functionality.
I'm not opposed to handling validation in the controller — as suggested by rageandqq and charlietfl — if it could be done easily. Looking around though, it looks like it could be tricky (given my requirements).
That is how angularjs works. If you use <input type="email" /> angular is not going to bind your input till input will be valid in this case value must be a proper e-mail address.
please read more here : https://github.com/angular/angular.js/issues/1426
The workaround I've come up with so far is to use jQuery to listen for the input change and update an object on $scope that I've called formRaw. It works. Still, I'm hoping someone will come along and show me a better way.
The updated example:
<div ng-app>
<div ng-controller="MyCtrl">
<form name="MyForm" novalidate>
Name: <input type="text" name="name" ng-model="contact.name" /><br/>
Name as you type: {{contact.name}}<br/>
Email: <input type="email" name="email" ng-model="contact.email" /><br/>
Email Model: {{contact.email}}<br/>
Email Form: {{formRaw.email}}
{{q}}
</form>
</div>
</div>
And controller:
function MyCtrl($scope) {
$scope.contact = {};
$scope.formRaw = {};
$('input[type=email]').on('keyup change', function () {
var input = $(this);
$scope.formRaw[input.attr('name')] = input.val();
$scope.$digest(); // FIXME: there's got to be a better way
});
}
(fiddle)
The type="email" attribute on your E-mail input is what is causing the DOM binding to mess up.
Changing it to type="text" works allows your {{contact.email}} to display correctly.
Edited JSFiddle.

angularjs ng-minlength validation is not working, form still being submitted

I am trying to submit the form on only successful validation.
validation is working for required but not working for ng-minlength
form input is invalid but form is still being submitted.
<form name="myForm" ng-submit="count = count + 1" ng-init="count=0" ng-app>
<div class="control-group" ng-class="{error: myForm.mobile.$invalid}">
<label class="control-label" for="mobile">Mobile</label>
<div class="controls">
<input type="text" name="mobile" placeholder="07XXXXXXXXX" ng-model="mobile" ng-minlength="11" required />
<span ng-show="myForm.mobile.$error.required" class="help-inline">Required</span>
<span ng-show="myForm.mobile.$error.minlength" class="help-inline">Mobile number should be minimum 11 character starting from 07</span>
</div>
</div>
<div class="control-group">
<div class="controls">
<input class="btn" type="submit" value ="submit" />
</div>
count: {{count}}<br />
<tt>myForm.$invalid = {{myForm.$invalid}}</tt><br/>
</div>
</form>
http://jsfiddle.net/pMMke/9/
what am I doing wrong.
I don't want to use submit button disable method.
This is what you are doing wrong: you are mixing two concepts, Angular validators and
HTML5 validators.
The required HTML5 validators, for instance, states that:
When present, it specifies that an input field must be filled out before submitting the form.
So, if you try to submit a form that has an input with this attribute, it will show a message explaining this to the user, and it will prevent the form from being sent. This is the behavior you want. Why isn't working for ng-minlength? Because ng-minlength is an Angular validator (you can tell because it begins with ng-), and it doesn't add any special behavior to the form. It simply set the input where it is located to invalid (and hence, the form), and let you decide what to do with it.
You have an option: you can use the pattern HTML5 validator, to specify the field requires at least 11 characters. It would like this:
<input type="text" pattern=".{11,}">
So when you submit a form containing this input, it will no be sent if the user has enter less than 11 characters.
But since we are it, and you are already using the pattern validator, you could use the regular expression in its full potential, and define something like:
<input type="text" pattern="07[0-9]{9}" />
Which will only admit values of 11 characters, that start by "07" and that contains only digits. I have modified your fiddle to show you how it would work: http://jsfiddle.net/helara/w35SQ/
I mistakenly used ngMaxlength="12" ngMinlength="6" instead of ng-minlength="6" ng-maxlength="12", it's working fine now.
Both ng-minlength & mg-maxlength works in AngularJS.
I've tested this in AngularJS version 1.3.
Make sure to use novalidate with <form> to disable browser's native validation.
This should work:
To enter mobile number
ng-show="myForm.mobile.$touched && myForm.mobile.$error.required"
For minimum length
ng-show="myForm.mobile.$touched && myForm.mobile.$error.minlength"
For maximum length
ng-show="myForm.mobile.$touched && myForm.mobile.$error.maxlength"
This work for me guys
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input ng-minlength="11" class="mdl-textfield__input" type="text" name="cpf" id="cpf" ng-model="avaliacao.cpf" ng-required="true" ng-pattern="/^\d+$/">
<label class="mdl-textfield__label" for="cpf">CPF *</label>
</div>
<p style="color: #d50000;" ng-show="myForm.cpf.$error.required && myForm.cpf.$dirty">Field Required</p>
<p style="color: #d50000;" ng-show="myForm.cpf.$error.pattern">Only numbers</p>
<p style="color: #d50000;" ng-show="myForm.cpf.$error.minlength">Min 11 Chars</p>
I'm facing the same issue, and I think you can only disable the button or ignore the entered value by yourself. You can also check the $valid property in your controller and ignore the value... It is not so nice, but I found no other way.

How to show 'invalid date' validation message for AngularStrap datetimepicker

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');
}

Resources