AngularJS Directive for checking if email already used - angularjs

I follow a solution for checking if a username is already present in the DB: defined in this topic angularjs: custom directive to check if a username exists
I put that in practice for checking if an email already exists in the DB. In my application a user can register until 5 emails.
When the user enters an email in the field, the query is correctly executed for checking if the email is already used in the database.
Some error messages have been implemented when the email format is not correct.
A message should be equally displayed when the email is already used (so present in the DB) but I have some problems for doing that (with the 5 fields for email addresses)
Here my controller:
// MY DIRECTIVE FOR CHECKING IF EMAIL IS ALREADY USED
app.directive('emailAvailable', function($timeout, $q, $http, ContactService) {
return {
restrict: 'AE',
require: 'ngModel',
link: function(scope, elm, attr, model) {
model.$asyncValidators.emailExists = function() {
email= elm.val();
return ContactService.searchContactByEmail(email).success(function(contact){
$timeout(function(){
if(contact.length >0){
model.$setValidity('emailExists', contact);
//model.$setValidity('unique', false); // For validation criteria in the form
scope.emailAlreadyExist='true';
scope.contacts = contact;
// THE VALUE IS CORRECTLY DISPLAYED IN THE CONSOLE
console.log("exist : " + scope.emailAlreadyExist);
}else{
model.$setValidity('emailExists', contact);
//model.$setValidity('unique', true); // For validation criteria in the form
scope.emailAlreadyExist='false';
scope.contacts = null;
// THE VALUE IS CORRECTLY DISPLAYED IN THE CONSOLE
console.log("exist : " + scope.emailAlreadyExist);
}
}, 600);
});
};
}
}
});
app.controller('ctrlAddContacts', function ($scope, ContactService){
$scope.title="Add a contact";
$scope.edit_oldContact = "false";
// ALLOW TO HAVE SEVERAL EMAILS
$scope.emails = [
{
}];
$scope.log = function() {
console.log($scope.emails);
};
$scope.add = function() {
var dataObj = {email:''};
$scope.emails.push(dataObj);
}
.........
});
Here my Factory:
app.factory('ContactService', function($http){
var factory={};
// CALL COLDFUSION FUNCTION
factory.searchContactByEmail=function(string){
if (string){
chaine='http://myapp/contacts.cfc?method=searchContactByEmail&contactEmail=' + string;
}else{
chaine='';
}
return $http.get(chaine);
};
return factory;
})
Here my Template:
<! --------------------------- MANAGE MAILS --------------------------->
<div ng-repeat="(key, email) in emails | limitTo : 5">
<div class="form-group">
<span ng-switch="$index">
<label ng-switch-when="0" for="txtEmail" class="col-sm-2 control-label">Main email</label>
<label ng-switch-default for="txtEmail" class="col-sm-2 control-label">Email {{$index+1}}</label>
</span>
<div class="col-sm-9" ng-switch="$index">
<input ng-switch-when="0" type="email" class="form-control"
name="txtEmail_{{$index}}" maxlength="100" placeholder="Enter main email"
required
ng-model="contact.EMAIL"
email-available
>
<input ng-switch-default type="email" class="form-control"
name="txtEmail_{{$index}}" maxlength="100" placeholder="Enter Email {{$index+1}}"
required
ng-model="contact['EMAIL_'+$index]"
email-available
>
<!-- THE VALUE emailAlreadyExist IS NOT DISPLAYED IN THE PAGE -->
<p>txtEmail_{{$index}} : {{emailAlreadyExist}}</p>
<! ----------------- Display the message when the email is already used ----------------->
<div ng-show="ContactForm['txtEmail_' + $index].$dirty && emailAlreadyExist=='true' " class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
Email is already used
</div>
<div ng-if="ContactForm['txtEmail_' + $index].$pending.emailExists">checking....</div>
<! ----------------- Display the message when the email is already used ----------------->
<div class="error-container"
ng-show="ContactForm['txtEmail_' + $index].$dirty && ContactForm['txtEmail_' + $index].$invalid">
<div ng-show="ContactForm['txtEmail_' + $index].$error.email" class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
That is not a valid email. Please input a valid email.
</div>
<div ng-show="ContactForm['txtEmail_' + $index].$error.required" class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
Your email is required.
</div>
<div ng-show="ContactForm['txtEmail_' + $index].$error.minlength" class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
Your email is required to be at least 3 characters
</div>
<div ng-show="ContactForm['txtEmail_' + $index].$error.maxlength" class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
Your email cannot be longer than 20 characters
</div>
</div>
</div>
<div class="col-sm-1" ng-show="$index == 0">
<a href="" ng-click="add()" ng-show="emails.length<5" class="inline btn btn-primary icon_email">
<span class="glyphicon glyphicon-plus icon2"></span><span class="addButton">Add</span>
</a>
</div>
</div>
</div>
<! --------------------------- MANAGE MAILS --------------------------->
Could you tell me how to update the script (of the directive I suppose) for displaying the message Email is already used ?
Thanks in advance for your help.

Please try below directive :
// MY DIRECTIVE FOR CHECKING IF EMAIL IS ALREADY USED
app.directive('emailAvailable', function($timeout, $q, $http, ContactService) {
return {
restrict: 'AE',
require: 'ngModel',
link: function(scope, elm, attr, model) {
model.$asyncValidators.emailExists = function() {
email= elm.val();
return ContactService.searchContactByEmail(email).success(function(contact){
$timeout(function(){
if(contact.length >0){
model.$setValidity('emailExists', true);
//model.$setValidity('unique', false); // For validation criteria in the form
scope.emailAlreadyExist='true';
scope.contacts = contact;
// THE VALUE IS CORRECTLY DISPLAYED IN THE CONSOLE
console.log("exist : " + scope.emailAlreadyExist);
}else{
model.$setValidity('emailExists', false);
//model.$setValidity('unique', true); // For validation criteria in the form
scope.emailAlreadyExist='false';
scope.contacts = null;
// THE VALUE IS CORRECTLY DISPLAYED IN THE CONSOLE
console.log("exist : " + scope.emailAlreadyExist);
}
}, 600);
});
};
}
}
});
and in template make following changes :
<! ----------------- Display the message when the email is already used ----------------->
<div ng-show="ContactForm['txtEmail_' + $index].$dirty && YOUR_FORM_NAME.$error.emailExists" class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
Email is already used
</div>
<div ng-if="ContactForm['txtEmail_' + $index].$pending.emailExists">checking....</div>
<! ----------------- Display the message when the email is already used ----------------->

Related

Add several emails and diplay defined values

My form allows to update and add several emails. The first email field (main email) is mandatory. After filling it's possible to click on a button "Add email" for adding a new email address. By this way it's possible to add 4 others emails (5 emails in total).
The system checks if the format of the email is correct and displays a message if necessary and register the data in a DB.
Here my view (manageContact.html)
<div class="panel-body">
<form name="ContactForm" class="form-horizontal" role="form" novalidate ng-submit="submitForm(contact)">
<!---------------- FOR UPDATING EMAILS FIELDS ------------ START --->
<div ng-repeat="(key, email) in emails | limitTo : 5" style="z-index:6">
<div class="form-group">
<span ng-switch="$index">
<label ng-switch-when="0" for="txtEmail" class="col-sm-2 control-label">Main email</label>
<label ng-switch-default for="txtEmail" class="col-sm-2 control-label">Email {{$index+1}}</label>
</span>
<div class="col-sm-9" ng-switch="$index">
<input ng-switch-when="0" type="email" class="form-control"
name="txtEmail_{{$index}}" maxlength="100" placeholder="Enter main email"
ng-model="contact.EMAIL">
<input ng-switch-default type="email" class="form-control"
name="txtEmail_{{$index}}" maxlength="100" placeholder="Enter Email {{$index+1}}"
ng-model="contact['EMAIL_'+$index]">
<div class="error-container"
ng-show="ContactForm['txtEmail_' + $index].$dirty && ContactForm['txtEmail_' + $index].$invalid">
<div ng-show="ContactForm['txtEmail_' + $index].$error.email" class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
That is not a valid email. Please input a valid email.
</div>
<div ng-show="ContactForm['txtEmail_' + $index].$error.required" class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
Your email is required.
</div>
</div>
</div>
<div class="col-sm-1" ng-show="$index == 0">
<a href="" ng-click="add()" ng-show="emails.length<5" class="inline btn btn-primary icon_email">
<span class="glyphicon glyphicon-plus icon2"></span><span class="addButton">Add email</span>
</a>
</div>
</div>
</div>
<!---------------- FOR UPDATING EMAILS FIELDS ------------ END --->
</form>
</div>
In order to see all emails registered of the contact, it's necessary with my current script to click on the button "Add email" each time that an email is registered for seeing data.
I would like to display the emails if they exist in the DB - so display each time the row (field + data). If it doesn't exist it's necessary to click on the button for adding an new email.
I have problem for doing that into my ng-switch and I don't how to do that in another way.
Here my controlers "ctrlEditContacts" and module (app.js):
var app=angular.module('ContactsApp', ['ngRoute', 'ui.bootstrap', 'ngDialog']);
app.factory('HttpInterceptor', ['$q', '$rootScope', function($q, $rootScope) {
return {
......
}
};
app.config(function($routeProvider, $httpProvider, ngDialogProvider){
...
});
app.controller('ctrlEditContacts', function ($scope, $routeParams, MyTextSearch, ContactService, ngDialog, $timeout){
//FOR ALLOWING SEVERAL EMAILS
$scope.emails = [
{
}];
$scope.log = function() {
console.log($scope.emails);
};
$scope.add = function() {
var dataObj = {email:''};
$scope.emails.push(dataObj);
}
ContactService.loadPersonById($routeParams.contactId).success(function(contact){
$scope.contact.ID = contact[0].ID;
$scope.contact.EMAIL = contact[0].EMAIL;
$scope.contact.EMAIL_1 = contact[0].EMAIL_1;
$scope.contact.EMAIL_2 = contact[0].EMAIL_2;
$scope.contact.EMAIL_3 = contact[0].EMAIL_3;
$scope.contact.EMAIL_4 = contact[0].EMAIL_4;
})
.error(function (data, status, header, config) {
...
}).finally(function() {
...
});
$scope.submitForm = function(contact){
if($scope.ContactForm.$valid){
ContactService.updatePerson(contact, $routeParams.contactId).success(function(){
alert('Person updated successfully');
})
.error(function (data, status, header, config) {
})
.finally(function() {
});
}
};
});
Sorry if I'm misunderstanding.
In this case, you need to loop for the number of contact's email info.
For example, if you get a kind of data below; you need to loop three times.
$scope.contact.ID = contact[0].ID;
$scope.contact.EMAIL = contact[0].EMAIL; // 'test1#mail.com'
$scope.contact.EMAIL_1 = contact[0].EMAIL_1; // 'test2#mail.com'
$scope.contact.EMAIL_2 = contact[0].EMAIL_2; // 'test3#mail.com'
$scope.contact.EMAIL_3 = contact[0].EMAIL_3; // ''
$scope.contact.EMAIL_4 = contact[0].EMAIL_4; // ''
// So 'emails' should be modified at this timing.
$scope.emails = [];
// Just for loop, so it doesn't matter what value you add.
$scope.emails.push($scope.contact.EMAIL);
$scope.emails.push($scope.contact.EMAIL_1);
$scope.emails.push($scope.contact.EMAIL_2);
After that, changing 'Add email' condition.
ng-show="$index == emails.length - 1"
jsfiddle

AngularJS Form - How to create and update several emails with ng-switch

I have a form in order to add / update one or several emails. The first email field is mandatory. After filling the field it's possible to click on "Add email" for adding a new email address. By this way it's possible to add 4 others emails (5 emails in total).
The system can verify if the format of the email is correct and display a message if necessary and register the data in a DB.
Here my view (manageContact.html)
<h3>{{title}}</h3>
<div class="panel panel-default" ng-show="authorRole==1">
<div class="panel-heading">
<div class="panel-title">Person Sheet</div>
</div>
<div class="panel-body">
<form name="ContactForm" class="form-horizontal" role="form" novalidate ng-submit="submitForm(contact)">
<!---------------- FOR UPDATING EMAILS FIELDS ------------ START --->
<div ng-repeat="(key, email) in emails | limitTo : 5" style="z-index:6">
<div class="form-group">
<span ng-switch="$index">
<label ng-switch-when="0" for="txtEmail" class="col-sm-2 control-label">Main email</label>
<label ng-switch-default for="txtEmail" class="col-sm-2 control-label">Email {{$index+1}}</label>
</span>
<div class="col-sm-9" ng-switch="$index">
<input ng-switch-when="0" type="email" class="form-control"
name="txtEmail_{{$index}}" maxlength="100" placeholder="Enter main email"
ng-model="contact.EMAIL">
<input ng-switch-default type="email" class="form-control"
name="txtEmail_{{$index}}" maxlength="100" placeholder="Enter Email {{$index+1}}"
ng-model="contact['EMAIL_'+$index]">
<div class="error-container"
ng-show="ContactForm['txtEmail_' + $index].$dirty && ContactForm['txtEmail_' + $index].$invalid">
<div ng-show="ContactForm['txtEmail_' + $index].$error.email" class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
That is not a valid email. Please input a valid email.
</div>
<div ng-show="ContactForm['txtEmail_' + $index].$error.required" class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
Your email is required.
</div>
<div ng-show="ContactForm['txtEmail_' + $index].$error.minlength" class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
Your email is required to be at least 3 characters
</div>
<div ng-show="ContactForm['txtEmail_' + $index].$error.maxlength" class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
Your email cannot be longer than 20 characters
</div>
</div>
</div>
<div class="col-sm-1" ng-show="$index == 0">
<a href="" ng-click="add()" ng-show="emails.length<5" class="inline btn btn-primary icon_email">
<span class="glyphicon glyphicon-plus icon2"></span><span class="addButton">Add email</span>
</a>
</div>
</div>
</div>
<!---------------- FOR UPDATING EMAILS FIELDS ------------ END --->
</form>
</div>
</div>
For adding a contact all is working and the emails are correctly registered.
For updating a contact I have a problem with the contact's emails. In order to see all emails registered of the contact, it's necessary with my current script to click on the button "Add email" each time that an email is registered for seeing data.
I would like to display the emails if they exist in the DB - so display each time the row (field + data). If it doesn't exist it's necessary to click on the button for adding an new email.
Could you please help me to update this code for doing that because I cannot do that directly in ng-switch?
Here my controlers "ctrlEditContacts" and module (app.js):
var app=angular.module('ContactsApp', ['ngRoute', 'ui.bootstrap', 'ngDialog']);
app.factory('HttpInterceptor', ['$q', '$rootScope', function($q, $rootScope) {
return {
......
}
};
app.config(function($routeProvider, $httpProvider, ngDialogProvider){
$httpProvider.defaults.cache = false;
if (!$httpProvider.defaults.headers.get) {
$httpProvider.defaults.headers.get = {};
}
$httpProvider.defaults.headers.get['If-Modified-Since'] = '0';
$routeProvider.when('/add-contacts',
{
templateUrl: 'template/manageContact.html',
controller: 'ctrlAddContacts'
})
.when('/edit-contacts/:contactId',
{
templateUrl: 'template/manageContact.html',
controller: 'ctrlEditContacts'
})
.otherwise({redirectTo:'/all-requests'});
});
app.controller('ctrlAddContacts', function ($scope, ContactService){
$scope.title="Add a contact";
// Allow to create several fields EMAIL
$scope.emails = [
{
}];
$scope.log = function() {
console.log($scope.emails);
};
$scope.add = function() {
var dataObj = {email:''};
$scope.emails.push(dataObj);
}
$scope.submitForm = function(contact){
if($scope.ContactForm.$valid){
// Send the object to the backend for saving data
ContactService.addNewPerson(contact).success(function(Person){
$scope.ContactForm.$setPristine();
$scope.contact= Person;
});
}
}
});
app.controller('ctrlEditContacts', function ($scope, $routeParams, MyTextSearch, ContactService, ngDialog, $timeout){
//FOR ALLOWING SEVERAL EMAILS
$scope.emails = [
{
}];
$scope.log = function() {
console.log($scope.emails);
};
$scope.add = function() {
var dataObj = {email:''};
$scope.emails.push(dataObj);
}
$scope.contact={};
if($routeParams.contactId){
$scope.title="Edit the contact";
}
ContactService.loadPersonById($routeParams.contactId).success(function(contact){
$scope.contact.ID = contact[0].ID;
$scope.contact.EMAIL = contact[0].EMAIL;
$scope.contact.EMAIL_1 = contact[0].EMAIL_1;
$scope.contact.EMAIL_2 = contact[0].EMAIL_2;
$scope.contact.EMAIL_3 = contact[0].EMAIL_3;
$scope.contact.EMAIL_4 = contact[0].EMAIL_4;
})
.error(function (data, status, header, config) {
console.log("Query loadPersonById ERROR");
console.log("status:" + status);
if (status==302) {
alert("Session expired - New Authentication requested");
}
}).finally(function() {
});
$scope.submitForm = function(contact){
if($scope.ContactForm.$valid){
ContactService.updatePerson(contact, $routeParams.contactId).success(function(){
alert('Person updated successfully');
})
.error(function (data, status, header, config) {
})
.finally(function() {
});
}
};
});
Here my factory (appService.js)
app.factory('ContactService', function($http){
var factory={};
factory.addNewPerson=function(objContact){
return $http.get('http://myapp/contacts.cfc?method=addNewPerson&jsStruct=' + JSON.stringify(objContact))
};
factory.updatePerson=function(objContact,id){
var params = {
method: "updatePerson",
contactid: id,
jsStruct: objContact
};
var config = { params: params };
return $http.get('http://myapp/contacts.cfc', config)
};
return factory;
})
If you have a best solution than ng-switch for doing that, please tell me.
Thank you in advance for your help.
Populate $scope.emails inside ContactService.loadPersonById()
I updated the controller:
app.controller('ctrlEditContacts', function ($scope, $routeParams, ContactService, ngDialog, $timeout){
//FOR ALLOWING SEVERAL EMAILS
$scope.emails = [];
$scope.log = function() {
console.log($scope.emails);
};
$scope.add = function() {
var dataObj = {email:''};
$scope.emails.push({});
};
$scope.contact={};
if($routeParams.contactId){
$scope.title="Edit the contact";
$scope.edit_oldContact = "true";
}
ContactService.loadPersonById($routeParams.contactId).success(function(contact){
console.log("Query loadPersonById OK");
$scope.contact.ID = contact[0].ID;
$scope.contact.EMAIL = contact[0].EMAIL;
$scope.contact.EMAIL_1 = contact[0].EMAIL_1;
$scope.contact.EMAIL_2 = contact[0].EMAIL_2;
$scope.contact.EMAIL_3 = contact[0].EMAIL_3;
$scope.contact.EMAIL_4 = contact[0].EMAIL_4;
// GET the emails already registered for displaying in the contact edit form
if($scope.contact.EMAIL.length > 0) {
$scope.emails.push($scope.contact.EMAIL);
}
if($scope.contact.EMAIL_1.length > 0) {
$scope.emails.push($scope.contact.EMAIL_1);
}
if($scope.contact.EMAIL_2.length > 0) {
$scope.emails.push($scope.contact.EMAIL_2);
}
if($scope.contact.EMAIL_3.length > 0) {
$scope.emails.push($scope.contact.EMAIL_3);
}
if($scope.contact.EMAIL_4.length > 0) {
$scope.emails.push($scope.contact.EMAIL_4);
}
})
.error(function (data, status, header, config) {
console.log("Query loadPersonById ERROR");
console.log("status:" + status);
}).finally(function() {
console.log("Query loadPersonById Finalized");
});
$scope.submitForm = function(contact){
//console.log(contact);
};
});
And The template:
<!---------------- FOR UPDATING EMAILS FIELDS ------------ START --->
<div ng-repeat="(key, email) in emails | limitTo : 5" style="z-index:6">
<div class="form-group">
<span ng-switch="$index">
<label ng-switch-when="0" for="txtEmail" class="col-sm-2 control-label">Main email</label>
<label ng-switch-default for="txtEmail" class="col-sm-2 control-label">Email {{$index+1}}</label>
</span>
<div class="col-sm-9" ng-switch="$index">
<input ng-switch-when="0" type="email" class="form-control"
name="txtEmail_{{$index}}" maxlength="100" placeholder="Enter main email"
ng-model="contact.EMAIL">
<input ng-switch-default type="email" class="form-control"
name="txtEmail_{{$index}}" maxlength="100" placeholder="Enter Email {{$index+1}}"
ng-model="contact['EMAIL_'+$index]">
<div ng-show="ContactForm['txtEmail_' + $index].$dirty && ContactForm['txtEmail_' + $index].$error.emailExists" class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
This email is already used
<ul id="contacts_list">
<li ng-repeat=" cont in ContactForm['txtEmail_' + $index].persons" style="position:relative; z-index:1">
<div angular-popover direction="right" template-url="template/popover.html" mode="mouseover">
{{ cont.lastname }} {{ cont.firsttname }}
</div>
</li>
</ul>
</div>
<div ng-if="ContactForm['txtEmail_' + $index].$pending.emailExists">checking....</div>
<div class="error-container"
ng-show="ContactForm['txtEmail_' + $index].$dirty && ContactForm['txtEmail_' + $index].$invalid">
<div ng-show="ContactForm['txtEmail_' + $index].$error.email" class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
That is not a valid email. Please input a valid email.
</div>
<div ng-show="ContactForm['txtEmail_' + $index].$error.required" class="alert alert-info" role="alert" style="margin-top:10px;">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
Your email is required.
</div>
</div>
</div>
<div class="col-sm-1" ng-show="$index == emails.length - 1">
<a href="" ng-click="add()" ng-show="emails.length<5" class="inline btn btn-primary icon_email">
<span class="glyphicon glyphicon-plus icon2"></span><span class="addButton">Add</span>
</a>
</div>
</div>
</div>
<!---------------- FOR UPDATING EMAILS FIELDS ------------ END --->

Angular object not binding

I have the following issue. I have 2 controllers defined for 2 separate functions.
The 1st controller handle my login and the second 1 handles forgot password.
Login controller binds well but forgot password controller does bind but not the object.
Controllers
var singlePageApp = angular.module('SinglePageApp',[]);
singlePageApp.controller('LoginController', function ($scope, $location, $window) {
$scope.isFormValid = false;
$scope.message = null;
$scope.login = null;
// Login object
$scope.Login = {
Email: '',
Password: '',
};
//check form validation
$scope.$watch('LoginForm.$valid', function (newValue) {
$scope.isFormValid = newValue;
});
$scope.submitForm = function () {
console.log('Form is submitted with:', $scope.login);
...
};
});
singlePageApp.controller('ForgotPasswordController', function ($scope, $location, $window) {
$scope.message = null;
$scope.password = null;
// Password object
$scope.Password = {
Email: '',
};
$scope.$watchGroup(['password', 'Password'], function (newValues, oldValues, scope) {
console.log(newValues);
});
$scope.forgotPassword = function () {
};
});
Login HTML
<div ng-controller="LoginController">
<form class="form-signin mt10" name="LoginForm">
<h2 class="form-signin-heading pwc">Please login</h2>
<div class="login-wrap">
<input ng-model="login.Email" id="tbEmail" name="Email" type="email" class="form-control" placeholder="Email" autofocus required>
<span class="error" ng-show="LoginForm.Email.$touched && LoginForm.Email.$error.required">Email is required</span>
<input ng-model="login.Password" id="tbPassword" name="Password" type="password" class="form-control" placeholder="Password" required>
<span class="error" ng-show="LoginForm.Password.$touched && LoginForm.Password.$error.required">Password is required</span>
<label class="checkbox">
<span class="pull-right">
#* Forgot Password?*#
Forgot Password?
</span>
</label>
<div class="clearfix"></div>
<button id="btnloginAdmin" type="button" ng-click="submitForm()" ng-disabled="LoginForm.$invalid && !!LoginForm.$error.email" class="btn btn-success btn-block">Login</button>
<div class="text-center">
<label style="color: red;" id="lblError" class="hasError-label clearfix">{{message}}</label>
<div class="error error-red"></div>
</div>
</div>
</form>
</div>
HTML Modal
<div ng-controller="ForgotPasswordController">
<div aria-hidden="false" aria-labelledby="myModalLabel" role="dialog" tabindex="-1" id="modalForgotPassword" class="modal fade">
<div class="modal-dialog">
<div class="modal-content" ng-form="fgForm">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">Forgot Password ?</h4>
</div>
<div class="modal-body">
<p>Enter your e-mail address below to reset your password.</p>
<input type="email" name="Email" ng-model="password.Email"
placeholder="Email" autocomplete="off"
class="form-control placeholder-no-fix" required>
<span class="error" ng-show="fgForm.Email.$touched && fgForm.Email.$error.required">Email is required</span>
<div class="text-center">
<label style="color: red;" id="fError" class="hasError-label clearfix">{{message}}</label>
<div class="error error-red"></div>
</div>
</div>
<div class="modal-footer">
<a href="javascript:;" class="btn btn-success" ng-disabled="fgForm.$invalid && !fgForm.$error.email" ng-click="forgotPassword();">
<i class="fa fa-check"></i> | Submit
</a>
<a href="javascript:;" class="btn btn-danger" data-dismiss="modal">
<i class="fa fa-times"></i> | Cancel
</a>
</div>
</div>
</div>
</div>
I have tried changing to bind to a single object 'password' but it states its undefined. Then I changed it to 'Password.Email' but then it stays empty.
The 2 controllers are bind on the same page so not sure if that is the issue.
Thank you in advance.

Bootstrap modal form elements unfocussable (on mobile/mobile emulation)

From the repo: https://github.com/jmsherry/kitchenapp
Live at: https://kitchenapp2.herokuapp.com
If you click the 'contact us' link in the bottom right corner of the screen a modal appears. The modal is coded like:
<div class="modal-container">
<button type="button" class="close" aria-label="Close" ng-click="$close(null)">
<span aria-hidden="true">×</span>
</button>
<div class="content">
<h1>Contact Us</h1>
<div class="contact-form">
<form ng-submit="vm.sendMessage(this)" novalidate name="contactForm">
<div class="form-group" ng-if="vm.user && vm.user.email">
<p class="faux-label">From: <span class="faux-value">{{vm.user.email}}</span></p>
</div>
<div class="form-group" ng-class="{ 'has-error' : contactForm.from.$invalid && !contactForm.from.$pristine }" ng-if="!vm.user || !vm.user.email">
<label for="subject">From</label>
<input type="email" name="from" id="from" class="form-control" placeholder="From" ng-model="vm.user.email" ng-maxlength="30" ng-required="true" autofocus>
<ul ng-if="contactForm.from.$invalid && !contactForm.from.$pristine" ng-messages="contactForm.from.$error" class="help-block list-unstyled">
<li ng-message="maxlength">The subject must be less than 30 characters.</li>
<li ng-message="email">Not a valid email. Please check carefully and try again...</li>
</ul>
</div>
<div class="form-group" ng-class="{ 'has-error' : contactForm.subject.$invalid && !contactForm.subject.$pristine }">
<label for="subject">Subject</label>
<input type="text" name="subject" id="subject" class="form-control" placeholder="Subject" ng-model="vm.email.subject" ng-maxlength="30">
<ul ng-if="contactForm.subject.$invalid && !contactForm.subject.$pristine" ng-messages="contactForm.subject.$error" class="help-block list-unstyled">
<li ng-message="maxlength">The subject must be less than 30 characters.</li>
</ul>
</div>
<div class="form-group" ng-class="{ 'has-error' : contactForm.message.$invalid && !contactForm.message.$pristine }">
<label for="message">Message</label>
<textarea name="message" id="message" class="form-control" placeholder="Message..." ng-model="vm.email.body" ng-required="true" ng-minlength="10" ng-maxlength="500"></textarea>
<ul ng-if="contactForm.message.$invalid && !contactForm.message.$pristine" ng-messages="contactForm.message.$error" class="help-block list-unstyled">
<li ng-message="required">A description is required.</li>
<li ng-message="minlength">The name must be longer than 10 characters.</li>
<li ng-message="maxlength">The name must be less than 500 characters.</li>
</ul>
</div>
<!-- <div class="form-group"> -->
<div class="checkbox">
<label for="cc_self">
<input type="checkbox" id="cc_self" name="cc_self" ng-model="vm.email.cc_self">Send a copy to my email.
</label>
</div>
<!-- </div> -->
<div class="form-group">
<div class="pull-right">
<button type="button" class="btn btn-default" ng-click="$close(null)">Cancel</button>
<button type="submit" class="btn btn-primary" ng-disabled="contactForm.$invalid">Send</button>
</div>
</div>
</form>
</div>
</div>
</div>
Controller looks like:
angular.module('kitchenapp.directives')
.controller('KaFooterCtrl', ['$scope', '$q', '$log', '$modal', 'Email', 'Auth', 'toastr', function ($scope, $q, $log, $modal, Email, Auth, toastr) {
var vm = this,
$user;
function contact(day) {
$log.log('contact fn', arguments);
$modal.open({
templateUrl: '/views/modals/contact-modal.html',
controller: function modalController($modalInstance, $scope) {
$scope.vm = this;
$scope.vm.email = vm.email;
$scope.vm.user = vm.user;
$scope.vm.sendMessage = function () {
$modalInstance.close();
$q.when(vm.user, function (user) {
var $emailSent = Email.sendEmail(vm.email, vm.user);
$q.when($emailSent, function (res) {
toastr.success('Email sent! Thank you for your interest...');
}, function () {
toastr.error('We\'re sorry your email hasn\'t been sent, please try again later...');
});
});
event.preventDefault();
event.stopPropagation();
};
},
contollerAs: 'vm'
});
}
vm.year = new Date().getFullYear();
vm.email = {};
$user = Auth.getUser();
$q.when($user, function (user) {
vm.user = user;
});
vm.contact = contact;
vm.name = 'KaFooterCtrl';
}])
.directive('kaFooter', function () {
return {
restrict: 'E',
replace: true,
templateUrl: 'directives/footer/footer.html',
scope: {
companyName: '#',
companyEmail: '#'
},
controller: 'KaFooterCtrl as vm',
bindToController: true
};
});
}());
For some reason the first element focusses once, but any further interaction and the elements are not focussable by touch or mouse. Any clues why?
Thanks
So, it transpires that this is a problem when ng-touch is used. ng-touch auto-blurs the fields (https://github.com/angular/angular.js/pull/11212). A fix is on the way, but for now the user #jdhiro suggests using a directive to stop propagation of the touchend event outside of your modal. See https://github.com/angular-ui/bootstrap/issues/2017#issuecomment-39515923 for more

Angular Form Validation correction

Here's Fiddle Link
Update--> works great with angular 1.3 by setting ng-model-options but i am using 1.2 :(
Here's Fiddle Link
Currently when user click on submit error comes up and goes away once he entered valid input. But What i want is not to hide the errors as user enter valid info.If user re-enter the correct data errors should go away only on clicking submit button only.
HTML
<div ng-app="app" ng-controller="MainCtrl">
<div class="panel-group">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">Order Form</h4>
</div>
<div class="panel-body">
<ng-include src="'form.html'"></ng-include>
</div>
</div>
</div>
<!-- kept seperate from the bootstrap markup to keep this example clean -->
<script type="text/ng-template" id="form.html">
<form name="form" valid-submit="sendForm()" novalidate>
<!-- call name-->
<div class="form-group clearfix" ng-class="{
'has-error': form.$submitted && form.orderNumber.$invalid,
'has-success': form.$submitted && form.orderNumber.$valid}">
<label class="col-sm-2 control-label" for="callName">Order Number</label>
<div class="col-sm-5">
<input id="orderNumber" name="orderNumber" class="form-control" type="text" ng-model="auth.orderNumber" ng-minlength="7" ng-maxlength="10" ng-pattern="/^[0-9]*$/" required ></input>
<div class="alert alert-danger" ng-show="form.$submitted && form.orderNumber.$error.required">Order Number required</div>
<span ng-show="form.$submitted && form.orderNumber.$error.pattern" class="help-block">Order number contains only numbers</span>
<span ng-show="form.$submitted && form.orderNumber.$error.minlength " class="help-block">Order number is too short</span>
<span ng-show="form.$submitted && form.orderNumber.$error.maxlength" class="help-block">Order number is too long</span>
</div>
</div>
<!-- last name-->
<div class="form-group clearfix" ng-class="{
'has-error': form.$submitted && form.confirmorderNumber.$invalid,
'has-success': form.$submitted && form.confirmorderNumber.$valid}">
<label class="col-sm-2 control-label" for="confirmorderNumber">Confirm Order Number</label>
<div class="col-sm-5">
<input id="lastName" name="confirmorderNumber" class="form-control" type="text" ng-model="person.lastName" data-match="auth.orderNumber" required></input>
<div class="alert alert-danger" ng-show="form.$submitted && form.confirmorderNumber.$error.required">required</div>
<span ng-show="form.$submitted && form.confirmorderNumber.$error.match" class="help-block">Order numbers must match</span>
</div>
</div>
<!-- form controls-->
<div class="form-group">
<button type="submit" class="btn btn-primary">Submit!</button>
</div>
</form>
</script>
</div>
js
var app = angular.module('app', []);
// directive that prevents submit if there are still form errors
app.directive('validSubmit', [ '$parse', function($parse) {
return {
// we need a form controller to be on the same element as this directive
// in other words: this directive can only be used on a <form>
require: 'form',
// one time action per form
link: function(scope, element, iAttrs, form) {
form.$submitted = false;
// get a hold of the function that handles submission when form is valid
var fn = $parse(iAttrs.validSubmit);
// register DOM event handler and wire into Angular's lifecycle with scope.$apply
element.on('submit', function(event) {
scope.$apply(function() {
// on submit event, set submitted to true (like the previous trick)
form.$submitted = true;
// if form is valid, execute the submission handler function and reset form submission state
if (form.$valid) {
fn(scope, { $event : event });
//form.$submitted = false;
}
});
});
}
};
}
]);
app.directive('match', function () {
return {
require: 'ngModel',
restrict: 'A',
scope: {
match: '='
},
link: function(scope, elem, attrs, ctrl) {
scope.$watch(function() {
var modelValue = ctrl.$modelValue || ctrl.$$invalidModelValue;
return (ctrl.$pristine && angular.isUndefined(modelValue)) || scope.match === modelValue;
}, function(currentValue) {
ctrl.$setValidity('match', currentValue);
});
}
};
});
// handle form submission when the form is completely valid
app.controller('MainCtrl', function($scope) {
$scope.sendForm = function() {
alert('form valid, sending request...');
};
});

Resources