Parsley Remote validation is not preventing form submission - angularjs

I am using Parsley Remote validation with angularJS..using the async validator with add new user form is working fine, it uses the API and checks if the user name is already existed, and the email as well, if the user name is there it returns a 200 status, which is not equal to 404 and an error message appears.. BUT when submitting the form, if I check the form.isvalid status it returns true, it is only validating the NON remote options. I am stuck there.
here is the web form
<form class="form-horizontal form-label-left" method="post" id="AddUserForm"
data-ui-jq="parsley"
data-parsley-remote
data-parsley-priority-enabled="false"
novalidate="novalidate">
<fieldset>
<legend>
By default validation is started only after at least 3 characters have been input.
</legend>
<div class="form-group">
<label class="control-label col-sm-3" for="basic">User Name</label>
<div class="col-sm-9">
<input type="text" name="userName" class="form-control" data-ng-model="user.userName" value=""
data-parsley-remote
data-parsley-remote-validator='checkusername'
data-parsley-trigger="focusout"
data-parsley-remote-message="User name is already registerd in the system"
required="required" />
<span class="help-block">
Username must be unique
</span>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="email">
E-mail
</label>
<div class="col-sm-9">
<input type="email" id="email" name="email" class="form-control" data-ng-model="user.email"
data-parsley-remote
data-parsley-remote-validator='checkemail'
data-parsley-trigger="focusout"
data-parsley-remote-message="Email is already registerd in the system"
required="required" />
<span class="help-block">
Email must be unique
</span>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3" for="password">
Password:
</label>
<div class="col-sm-9">
<input type="password" id="password" name="password" class="form-control mb-sm" data-ng-model="user.password"
data-parsley-trigger="change"
data-parsley-minlength="6"
required="required" />
<input type="password" id="password-r" name="password-r" class="form-control" placeholder="Confrim Password" data-ng-model="user.confirmPassword"
data-parsley-trigger="change"
data-parsley-minlength="6"
data-parsley-equalto="#password"
required="required" />
</div>
</div>
</fieldset>
<div class="form-actions">
<button type="submit" data-ng-click="AddNewUser($event)" class="btn btn-danger btn-rounded pull-right">Validate & Submit</button>
<button type="button" class="btn btn-default btn-rounded">Cancel</button>
</div>
</form>
and this is my async validator:
window.ParsleyExtend = {
asyncValidators: {
checkusername: {
fn: function (xhr) {
console.log($('[name="userName"]'));
return 404 === xhr.status;
},
url: authService.serviceBase + 'api/account/CheckUserName/' //+ $('[name="userName"]').text()
},
checkemail: {
fn: function (xhr) {
console.log($('[name="email"]'));
return 404 === xhr.status;
},
url: authService.serviceBase + 'api/account/CheckEmail/'// + $('[name="email"]').text()
}
}
};
and this is how I validate the form:
$scope.AddNewUser = function ($event) {
$event.preventDefault();
//THis resturns true allways when the remote validation is not valid,, but when other non remote valdiation happens is works fine
$('#AddUserForm').parsley().validate();
//and this if statement resturns true allways even when the remote validation is not valid,, but when other non remote valdiation happens is works fine
if ($('#AddUserForm').parsley().isValid()) {
authService.saveRegistration($scope.user).then(function (response) {
$scope.savedSuccessfully = true;
// $scope.message = "User has been registered successfully, you will be redicted to login page in 2 seconds.";
//startTimer();
},
function (response) {
var errors = [];
for (var key in response.data.modelState) {
for (var i = 0; i < response.data.modelState[key].length; i++) {
errors.push(response.data.modelState[key][i]);
}
}
$scope.message = "Failed to register user due to:" + errors.join(' ');
});
}
};

just found the answer.. I have to use asyncIsValid() and asyncValidate() along with the normal isValid() and Validate() methods.. so the code will be as follows:
$('#AddUserForm').parsley().asyncValidate();
if($('#AddUserForm').parsley().isValid() && $('#AddUserForm').parsley().isAsyncValid()) {
....}

I first check each field to make sure it is validated, if a field is not validated, my ok variable will be set to false.
Here is some sample code:
$(function() {
var ok;
$('#signup').parsley().on('field:validated', function() {
ok = $('.parsley-error').length === 0;
})
.on('form:submit', function() {
if (ok) return true;
else return false;
});
});
Parsley.addAsyncValidator('checkExists', function(xhr) {
return false === xhr.responseJSON;
}, '/data-management/verify-data?filter=signup');

Related

Get form input value from angularjs

I'm using Angularjs to submit the form then pass the value to my laravel function.
This is my HTML code
<form class="form-horizontal" method="post" name='form' novalidate ng-submit="submit()" ng-controller="syncApiCtrl">
<div class="col-lg-10">
<div class="input-group">
<input type="text" class="form-control" id="name" name="name" placeholder="Your_name">
</div>
</div>
<div class="form-group">
<div class="col-lg-10 col-lg-offset-2">
<input type="submit" name="sale" value="Sync Sale" class="btn btn-primary"></input>
<input type="submit" novalidate ng-click="sync_product(record)" name="product" value="Sync Product" class="btn btn-primary"></input>
</div>
</div>
</form>
This is my JS
$scope.submit = function () {
//$scope.form.$submitted = true;
// proceed if form valid
if ($scope.form.$valid) {
// is loading
$scope.loading = true;
// prepare data packet
var data = {};
angular.forEach($scope.form, function (v, k) {
if (k.indexOf('$') < 0 && typeof v.$dirty !== 'undefined' && v.$dirty) {
data[k] = v.$modelValue;
}
});
}
};
This is my laravel function
public function sync_sale() {
$name= preg_replace('/[^A-Za-z0-9\_]/', '', Input::get('name'));
Debugbar::info($name);
}
My laravel function always can't get the value after user submit a form.
You should have bound your input to a ng-model. This one is working. You should use data binding methods in angularJs.
<input type="text" class="form-control" id="name" name="name" placeholder="Your_name" ng-model="name">

not able to access form contents such as username... in my controller AngularjS

I am trying to implement registration functionality where in the user details from the form will be saved to the database. To do that I am trying to access username in my controller and it gives undefined.
username is:undefined signup.controller.js (13,9)
(function() {
var app = angular.module("myApp");
app.controller("registerController", function(registrationService) {
var self = this;
self.registrationFormSubmission = function() {
// $rootScope.id=1;
var usern = self.username;
console.log("username is:" + self.form.username);
self.user = {};
self.user = {
id: 1,
username: self.username,
firstname: self.firstname,
lastname: self.lastname,
email: self.email,
password: ""
};
return self.user;
registrationService
.saveUserInfo(user)
.then(function() {
self.suceess = "user registered successfully";
console.log("form submission successful");
window.alert("form submission successful");
})
.then(function() {
self.failure = "Error occurred while registering user!";
});
};
});
})();
<form name="registerctrl.form" role="form">
<div class="container-fluid">
<h4>Register</h4>
<p>Please fill in this form to create an account.</p>
<hr>
<div class="form-group" ng-class="{'has-error':form.username.$dirty && form.username.$error.required}">
<label for="username">Username:</label>
<input type="text" class="form-control" id="username" placeholder="Enter username" ng-modal="registerctrl.username" name="username" required>
<span ng-show="form.username.$dirty && form.username.$error.required" class="help-block">Username is required</span>
{{form.username}}
</div>
<div class="form-group" ng-class="{'has-error':form.firstname.$dirty && form.firstname.$error.required}">
<label for="firstname">Firstname:</label>
<input type="text" class="form-control" id="firstname" placeholder="Enter firstname" ng-modal="registerctrl.firstname" name="firstname" required>
<span ng-show="form.firstname.$dirty && form.firstname.$error.required" class="help-block">Firstname is required</span>
<hr>
<p>By creating an account you agree to our Terms & Privacy.</p>
<button class="button" ng-click="registerctrl.registrationFormSubmission()">Register</button>
<p>Already have an account? Sign in.</p>
</div>
</div>
</form>
Seems like the problem is in typo.
You have
ng-modal="registerctrl.username"
Should be
ng-model="registerctrl.username"

Angular form submissions issues

This is my signup.html file i want to take only password and username from this form to my controller.but I not able to access form elements through this !
<ion-view view-title="Sign Up">
<ion-content ng-controller="signup">
<div class="figure_img">
<img src="img/logo_image.png">
</div>
<form name="myForm">
<div class="list">
<label class="item item-input">
<input type="text" placeholder="Email ID" id="email" name="email" ng-model="formData.email"
required>
<span ng-show="myForm.email.$error.required && myForm.email.$dirty">required</span>
<span ng-show="!myForm.email.$error.required && myForm.email.$error.email && myForm.email.$dirty">invalid email</span>
</label>
<label class="item item-input">
<input type="password" placeholder="Password" id="password" name="password"
ng-model="formData.password" required>
<span ng-show="myForm.password.$error.required && myForm.password.$dirty">required</span>
</label>
<label class="item item-input">
<input type="password" placeholder="Confirm Password" id="password_c" name="password_c" ng-model="formData.password_c" valid-password-c required>
<span ng-show="myForm.password_c.$error.required && myForm.password_c.$dirty">Please confirm your password.</span>
<span ng-show="!myForm.password_c.$error.required && myForm.password_c.$error.noMatch && myForm.password.$dirty">Passwords do not match.</span>
</label>
<div class="contain-body">
<button class="button button-block button-positive" ng-click="signup(myForm)">SignUp</button>
</div>
</div>
</form>
</ion-content>
</ion-view>
this is my controller for signup
app.controller("signup", function ($scope,$http,$ionicPopup,URL,$ionicLoading,$timeout,$state) {
$scope.data = {
email :'',
password :''
};
$scope.signup = function (data) {
console.log(data);
$http.post(URL.url + '/registration',data)
.success(function () {
$ionicLoading.show({template:'<ion-spinner class="spinner-energized"></ion-spinner>Complete your Registration through Email'});
$timeout(function () {
$ionicLoading.hide();
$ionicHistory.clearCache().then(function() {
$state.go('EmailLogin') ;
});
},5000);
}).error(function (response) {
$ionicPopup.alert({
title: 'Sign-Up failed!',
template:response.errors.email
});
});
}
});
how could i take only password and username in my controller ..
so that it gets easy to signup !
You are actually passing the form controller to your signup method. This is not what you want.
You already got access to your email and password field values through formData.email and formData.password in your view, so you can adjust the call to the signup by including formData as suggested in the comments.
But as you declare $scope.data is your controller, you might want to reuse those instead of formData in your ng-model directive of the view, because currently this data object does not seem to be used.
Create an object in the function using the data you received. Just do something like var reqData = { email: data.email, password: data.password }; and then do $http.post(URL.url + '/registration',reqData).
Hope it helps.

Validating form on submit in angular

Hello i am trying to make my validation display on form submit but validation does not work, form gets sent anyway. This is my form:
<form class="form-horizontal col-md-10" role="form" name="authenticationForm" ng-controller="AuthenticationController as authentication" ng-submit="authenticate(authenticationForm.$valid)" novalidate>
<hr>
<br>
<div class="form-group" ng-class="{ 'has-error' : authenticationForm.email.$invalid && !authenticationForm.email.$pristine && submitted }">
<div class="col-md-4">
<label for="email">Email: </label>
</div>
<div class="col-md-6">
<input type="email" id="email" name="email" ng-model="email" class="form-control" ng-required/>
<p ng-show="authenticationForm.email.$invalid && !authenticationForm.email.$pristine && submitted" class="help-block">
Your email address is required.
</p>
</div>
</div>
<div class="form-group" ng-class="{ 'has-error' : authenticationForm.password.$invalid && !authenticationForm.password.$pristine && submitted }">
<div class="col-md-4">
<label for="password">Password</label>
</div>
<div class="col-md-6">
<input type="password" id="password" name="password" ng-model="password" class="form-control" ng-required/>
<p ng-show="authenticationForm.password.$invalid && !authenticationForm.password.$pristine && submitted" class="help-block">
Password is required.
</p>
</div>
</div>
<div class="form-group">
<div class="col-md-6 col-md-offset-4">
<div class="checkbox">
<label>
<input type="checkbox" name="remember"> Remember Me
</label>
</div>
</div>
</div>
<span class="help-block errorMessages" ng-show="user.input.errors !== undefined">
<div class="alert alert-danger">
<ul class="list">
<li ng-repeat="error in user.input.errors">
<i class="fa fa-times"></i> <% error %>
</li>
</ul>
</div>
</span>
<div class="form-group">
<div class="col-md-12">
<br/>
<hr>
<button class="big-red-button" type="submit">Login <i class="glyphicon glyphicon-chevron-right"></i></button>
<a class="btn btn-link" href="{{ url('/password/email') }}">Forgot Your Password?</a>
</div>
</div>
</form>
This is my controller function:
$scope.authenticate = function(isValid) {
// settting submitted to true
$scope.submitted = true;
// check to make sure the form is completely valid
if (isValid) {
var req = {
method: 'POST',
url: '/auth/login',
headers: {
'X-XSRF-Token': $("meta[name='csrf_token']").attr("content")
},
data: {
email: $scope.email,
password: $scope.password
}
}
$http(req)
.success(function (data, status, headers, config) {
if (data.url !== undefined)
{
window.location.href = data.url;
}
})
.error(function (data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
//alert(data);
});
}
};
Can someone please point out what i am doing wrong here? Thanks. :)
You should be able to check $scope.authenticationForm.$valid and prevent the xhr, and you can also visually set the submit button to ng-disabled="authenticationForm.$invalid" so they can't click the button until it's valid. That disabled setting won't prevent submitting the form other ways (enter key, etc).
Have you checked the boolean coming to you? It should be false is there's a validation error.
As you are using controllerAs syntax then you should use each ng-model as
authentication.email & authentication.password
Email Field
<input type="email" id="email" name="email" ng-model="authentication.email"
class="form-control" ng-required/>
Password Field
<input type="password" id="password" name="password" ng-model="authentication.password"
class="form-control" ng-required/>
then inside controller you could get this value by this.email & this.password
That happened to me too. Change ng-required to required, make sure the isValid boolean is actually false if it's not a valid form and take out the novalidate in the form element.
Sometimes the angular $valid is not always accurate. Also, I think you should have put ng-required="true" or some function that returns true, if you are using ng-required.
Check out this article: http://arnaldocapo.com/blog/post/detect-if-html-5-validation-ui-is-present/53
Just replace every where ng-required to required like:
<input type="text" required/>
and also set ng-controller="AuthenticationController " instead of
ng-controller="AuthenticationController as authentication"

Validate form field only on submit or user input

I have form fields that are validated using required. The problem is, that the error is displayed immediately when the form is rendered. I want it only to be displayed after the user actually typed in the text field, or on submit.
How can I implement this?
Use $dirty flag to show the error only after user interacted with the input:
<div>
<input type="email" name="email" ng-model="user.email" required />
<span ng-show="form.email.$dirty && form.email.$error.required">Email is required</span>
</div>
If you want to trigger the errors only after the user has submitted the form than you may use a separate flag variable as in:
<form ng-submit="submit()" name="form" ng-controller="MyCtrl">
<div>
<input type="email" name="email" ng-model="user.email" required />
<span ng-show="(form.email.$dirty || submitted) && form.email.$error.required">
Email is required
</span>
</div>
<div>
<button type="submit">Submit</button>
</div>
</form>
function MyCtrl($scope){
$scope.submit = function(){
// Set the 'submitted' flag to true
$scope.submitted = true;
// Send the form to server
// $http.post ...
}
};
Then, if all that JS inside ng-showexpression looks too much for you, you can abstract it into a separate method:
function MyCtrl($scope){
$scope.submit = function(){
// Set the 'submitted' flag to true
$scope.submitted = true;
// Send the form to server
// $http.post ...
}
$scope.hasError = function(field, validation){
if(validation){
return ($scope.form[field].$dirty && $scope.form[field].$error[validation]) || ($scope.submitted && $scope.form[field].$error[validation]);
}
return ($scope.form[field].$dirty && $scope.form[field].$invalid) || ($scope.submitted && $scope.form[field].$invalid);
};
};
<form ng-submit="submit()" name="form">
<div>
<input type="email" name="email" ng-model="user.email" required />
<span ng-show="hasError('email', 'required')">required</span>
</div>
<div>
<button type="submit">Submit</button>
</div>
</form>
If you want to show error messages on form submission, you can use condition form.$submitted to check if an attempt was made to submit the form. Check following example.
<form name="myForm" novalidate ng-submit="myForm.$valid && createUser()">
<input type="text" name="name" ng-model="user.name" placeholder="Enter name of user" required>
<div ng-messages="myForm.name.$error" ng-if="myForm.$submitted">
<div ng-message="required">Please enter user name.</div>
</div>
<input type="text" name="address" ng-model="user.address" placeholder="Enter Address" required ng-maxlength="30">
<div ng-messages="myForm.name.$error" ng-if="myForm.$submitted">
<div ng-message="required">Please enter user address.</div>
<div ng-message="maxlength">Should be less than 30 chars</div>
</div>
<button type="submit">
Create user
</button>
</form>
You can use angularjs form state form.$submitted.
Initially form.$submitted value will be false and will became true after successful form submit.
Erik Aigner,
Please use $dirty(The field has been modified) and $invalid (The field content is not valid).
Please check below examples for angular form validation
1)
Validation example HTML for user enter inputs:
<form ng-app="myApp" ng-controller="validateCtrl" name="myForm" novalidate>
<p>Email:<br>
<input type="email" name="email" ng-model="email" required>
<span ng-show="myForm.email.$dirty && myForm.email.$invalid">
<span ng-show="myForm.email.$error.required">Email is required.</span>
<span ng-show="myForm.email.$error.email">Invalid email address.</span>
</span>
</p>
</form>
2)
Validation example HTML/Js for user submits :
<form ng-app="myApp" ng-controller="validateCtrl" name="myForm" novalidate form-submit-validation="">
<p>Email:<br>
<input type="email" name="email" ng-model="email" required>
<span ng-show="submitted || myForm.email.$dirty && myForm.email.$invalid">
<span ng-show="myForm.email.$error.required">Email is required.</span>
<span ng-show="myForm.email.$error.email">Invalid email address.</span>
</span>
</p>
<p>
<input type="submit">
</p>
</form>
Custom Directive :
app.directive('formSubmitValidation', function () {
return {
require: 'form',
compile: function (tElem, tAttr) {
tElem.data('augmented', true);
return function (scope, elem, attr, form) {
elem.on('submit', function ($event) {
scope.$broadcast('form:submit', form);
if (!form.$valid) {
$event.preventDefault();
}
scope.$apply(function () {
scope.submitted = true;
});
});
}
}
};
})
3)
you don't want use directive use ng-change function like below
<form ng-app="myApp" ng-controller="validateCtrl" name="myForm" novalidate ng-change="submitFun()">
<p>Email:<br>
<input type="email" name="email" ng-model="email" required>
<span ng-show="submitted || myForm.email.$dirty && myForm.email.$invalid">
<span ng-show="myForm.email.$error.required">Email is required.</span>
<span ng-show="myForm.email.$error.email">Invalid email address.</span>
</span>
</p>
<p>
<input type="submit">
</p>
</form>
Controller SubmitFun() JS:
var app = angular.module('example', []);
app.controller('exampleCntl', function($scope) {
$scope.submitFun = function($event) {
$scope.submitted = true;
if (!$scope.myForm.$valid)
{
$event.preventDefault();
}
}
});
Invoking of validation on form element could be handled by triggering change event on this element:
a) exemple: trigger change on separated element in form
$scope.formName.elementName.$$element.change();
b) exemple: trigger change event for each of form elements for example on ng-submit, ng-click, ng-blur ...
vm.triggerChangeForFormElements = function() {
// trigger change event for each of form elements
angular.forEach($scope.formName, function (element, name) {
if (!name.startsWith('$')) {
element.$$element.change();
}
});
};
c) and one more way for that
var handdleChange = function(form){
var formFields = angular.element(form)[0].$$controls;
angular.forEach(formFields, function(field){
field.$$element.change();
});
};

Resources