I tried using jquery validate but i've spent more than 4 hours to search how to solve my problem but couldn't find it. The problem is when I tried using jquery validate for filesize in multidimensional array, it doesn't work. It can still submit the form and not showing the error message.
Here is it my field
var numberIncr = 1;
$('#add-berkas').click(function () {
var box_html = $('<div class="text-box form-group row">\n' +
' <div class="col-sm-8">\n' +
' <input type="text" name="berkas['+numberIncr+'][nama]" placeholder="Nama File" class="form-control" required>\n' +
' </div>\n' +
' <div class="col-sm-4">\n' +
' <input type="file" name="berkas['+numberIncr+'][file]" id="berkasfile'+numberIncr+'" accept="application/pdf" required/>\n' +
' <button id="remove-berkas" class="btn btn-sm btn-danger remove-box" type="button"><i class="fa fa-trash"></i></button>\n' +
' </div>\n' +
' </div>');
$('.text-box:last').after(box_html);
box_html.fadeIn('slow');
numberIncr++;
});
And this is the validate
$.validator.addMethod('filesize', function (value, element, param) {
return this.optional(element) || (element.files[0].size <= param)
}, 'File size must be less than {0}');
var berkas = $('input[name^="berkas"]');
berkas.filter('input[name$="[file]"]').each(function() {
$(this).rules("add", {
extension: "pdf", filesize:1048576,
messages: "Berkas must be PDF and less than 1MB"
});
});
$("#form").validate({
rules: {
surat: {extension: "pdf", filesize: 1048576, },
},
messages: {
surat: "Surat must be PDF and less than 1MB",
},
errorPlacement: function(error,element){
showErrorMessage(error.text());
},
submitHandler: function(form) {
form.submit();
},
highlight: function(element, errorClass) {
return false;
}
});
Your problem is caused by presumably only calling this code once on page load, when the fields don't yet exist...
berkas.filter('input[name$="[file]"]').each(function() {
$(this).rules("add", {
extension: "pdf", filesize:1048576,
messages: "Berkas must be PDF and less than 1MB"
});
});
There are no matching fields at the time you call this code. The whole point of this method is for you to dynamically add the rules after you create each field.
You must call it immediately after adding a new field. Put it inside the click handler near the bottom.
var numberIncr = 1;
$('#add-berkas').click(function () {
var box_html = $('<div class="text-box form-group row">\n' +
.....
' </div>');
$('.text-box:last').after(box_html);
box_html.fadeIn('slow');
// add rules to new field here
$('[name="berkas[' + numberIncr + '][file]"]').rules("add", {
extension: "pdf", filesize:1048576,
messages: "Berkas must be PDF and less than 1MB"
});
numberIncr++;
});
You wouldn't need an .each() since you only create one field on each click. Just target the new field and add the rule.
Related
I am using a 'required' and 'email' validators on the 'email' input field. The validators make use of parsers and formatters and they work fine. However, I also have some validation on 'bind' event.
Here is the directive:
angular.module('simpleRepairApp')
.directive('uniqueEmail', function (Checker) {
return {
require:'ngModel',
restrict:'A',
link:function ($scope, element, attrs, model) {
var last = '';
var current = '';
element.bind('blur', function() {
current = element.val();
console.log(current, last);
if(current !== last){
Checker.email({ email:current }).then(
function(response) {
model.$setValidity('uniqueEmail', response.available);
}
);
}
last = current;
});
}
};
});
I need to check if the email already exists in the database or not after user clicks out of the field (I do not want to check upon every key press or change).
The problem I am having is, after the unique validation is performed, it shows the unique error message, but after you type to correct the email, the model value stays undefined. You have to click out of the input, then the value in the model in defined again.
Anyone can help me solve this, it is driving me nuts!:)
WORKING SOLUTION:
angular.module('simpleRepairApp')
.directive('emailUnique', function () {
return {
restrict: 'E',
require: ['form', 'ngModel'],
scope: {
'form': '=form',
'model': '=ngModel',
'labelClass': '#',
'inputClass': '#'
},
compile: function(element, attrs)
{
if (!attrs.labelClass) { attrs.labelClass = 'col-sm-4'; }
if (!attrs.inputClass) { attrs.inputClass = 'col-sm-8'; }
attrs.required = attrs.required == 'true';
},
controller: function($scope, Checker) {
$scope.checkEmail = function() {
var email = $scope.form.email.$viewValue;
var checkField = $scope.form.emailCheck;
Checker.email({ email:email }).then(
function(response) {
checkField.$setValidity('unique', response.available);
$scope.form.$setValidity('check', true);
checkField.hasVisit = true;
}
);
};
$scope.setUnchecked = function() {
console.log($scope.form);
$scope.form.emailCheck.hasVisited = false;
$scope.form.$setValidity('check', false);
$scope.form.emailCheck.$setValidity('unique', true);
};
},
template: '<div ng-class="{ \'has-error\' : !form.email.$valid || !form.emailCheck.$valid }">' +
'<label class="{{ labelClass }} control-label required" for="email" translate>E-mail</label>' +
'<div class="{{ inputClass }}">' +
'<input name="email" class="form-control" type="email" id="email" ng-model="model" ng-change="setUnchecked()" ng-blur="checkEmail()" ng-required="true" autocomplete="off">' +
'<div class="help-block" ng-show="(!form.email.$valid || !form.emailCheck.$valid) && !form.email.$pristine">' +
'<div ng-messages="form.email.$error">' +
'<div ng-message="required"><span translate>Please enter your e-mail.</span></div>' +
'<div ng-message="email"><span translate>Please enter a valid e-mail.</span></div>' +
'</div> ' +
'<div ng-messages="form.emailCheck.$error">' +
'<div ng-message="check"><span translate>E-mail will be checked upon blur.</span></div>' +
'<div ng-message="unique"><span translate>This e-mail is already in use.</span></div>' +
'</div> ' +
'</div>' +
'<input name="emailCheck" type="hidden" class="form-control" ng-model="checked">' +
'<div class="help-block" ng-messages="form.emailCheck.$error" ng-show="!form.emailCheck.$valid">' +
'</div>' +
'</div>' +
'</div>'
};
});
I think you might be complicating things a bit by making a directive, why don't you simply add a watcher to your controller?
Note: I'm not familiar if any of these methods will work for you, but I'm adding them as an illustrative purpose of not binding to the "blur" event, but rather have the events get triggered when the MODEL changes. Which is what angular is designed to do. I'm also making an assumption that your Checker is handling the promises correctly
First alternative method (using $watch)
<form name="myForm" ng-controller="ExampleController">
<input type="email" name="input" ng-model="text" required />
</form>
Then in your ng-app controller:
function isNullOrUndefined(value) {
return (value == 'undefined' || value == null);
}
//listener on the ng-model='text', waiting for the data to get dirty
$scope.$watch('text', function (newValue, oldValue) {
if (newValue != oldValue)
{
var truthyVal = !(isNullOrUndefined(newValue));
if (truthyVal) {
//angular's way of checking validity as well
//$scope.myForm.text.$valid
Checker.email({ email:current }).then(
function(response) {
model.$setValidity('textErr', response.available);
}
}
}
}, true);
Second alternative method (using ng-change):
<form name="myForm" ng-controller="ExampleController">
<input type="email" name="input" ng-model="text" ng-change="checkEmail()" required />
</form>
$scope.checkEmail = function(){
Checker.email({ email:current }).then(
function(response) {
model.$setValidity('textErr', response.available);
}
}
Because you are binding on the blur event, the validation won't work the way you want. You will have to click out of the field before that function can run. If you indeed want it to validate when they finish typing the email, then you will have to bind to some sort of key event.
My suggestion is to bind to keyup, and only do the server-side check when the email address appears to be of valid syntax.
The span's innerHTML change depends on AJAX. If the span's innerHTML is <img src="images/not-available.png">, then submit should return false.
HTML:
<form onsubmit="return validateemail()">
<span id= "message"><img src="images/not-available.png"></span>
<button id='submit' name="submit" type='submit'>Submit</button>
</form>
JS:
function validateemail()
{
var munx = document.getElementById("message").innerHTML;
var muny = '<img src="images/not-available.png">';
if (munx == muny)
{
alert ("Email id is already Exist");
return false;
}
}
I tried this code, but it doesn't work.
You can use jQuery Validation Plugin (http://jqueryvalidation.org/validate/) in your project. This is standard form validation that you can use in diffrent way.
for example:
$(".selector").validate({
invalidHandler: function(event, validator) {
// 'this' refers to the form
var errors = validator.numberOfInvalids();
if (errors) {
var message = errors == 1
? 'You missed 1 field. It has been highlighted'
: 'You missed ' + errors + ' fields. They have been highlighted';
$("div.error span").html(message);
$("div.error").show();
} else {
$("div.error").hide();
}
}
});
example of ajax: Submits the form via Ajax when valid.
$(".selector").validate({
submitHandler: function(form) {
$(form).ajaxSubmit();
}
});
You are validating it wrong.
see this:
<span id= "message"><img src="images/not-available.png"></span>
and now see this:
var muny = '<img src="images/not-available.png"/>';
can you notice the extra "/" character in second one i.e just before img closing bracket. Thats causing the problem.
So replace with this one:
var muny = '<img src="images/not-available.png">';
I have a problem validating dynamic addes inputs on GridView. I have partial views and each partial view has its own GridView. On my _Layout I have all links to scripts like jquery.validation.min.s etc. GridView is wrapped in a form so I have form id. Function for appending new row to GridView:
<script type="text/javascript">
$(function () {
$(document).on('click', '.addCostObject', function () {
var existRowSave = $('.saveCostObject').length;
var existRowEdit = $('.updateCostObject').length;
if (existRowSave == 0 && existRowEdit == 0) {
$('#gridCostObject tbody').append('<tr>' +
'<td><img src="#Url.Content("~/Images/save_.png")" /> <img src="#Url.Content("~/Images/save_cancel.png")" /></td>' +
'<td></td>' +
'<td><input type="text" name=\'costObject\' id=\'costObjectName\' class=\'costObjectNameClass\' placeholder=\'Cost Object Type\' data-val="true" data-val-required="This field is required"/></td>' +
'<td><input type="text" name=\'objectIdName\' id=\'objectId\' class=\'objectIdClass\' placeholder=\'Object ID\' data-val="true" data-val-required="This field is required"/></td>' +
'</tr>');
}
else {
alert('Save/Update or Cancel your previous record!');
}
})
event.stopImmediatePropagation();
})
At the end of my view I have a script for vaildating and appending rules:
<script type="text/javascript">
$(function() {
$("#gridCostObject").validate("add", {
rules: {
costObject: {
required: true
},
objectIdName: {
required: true,
digits: true
}
},
messages: {
objectIdName: {
digits: "Object id contains only digits"
}
}
})
})
At the save click, debugger always says that object form does not have 'valid'. I've tried putting my script everywhere in my view and trying all possible combination so far. What am I doing wrong?
$.validator.unobtrusive.parse('#yourFormSelector')
should help :)
It reinitializes the validation for your form - after that, the method will be available for your newly loaded elements
I'd like to create a webpage where the user can add and remove sets of form fields by means of one add button and remove buttons related to the set to be removed. Entered values will be checked by means jquery validate, for which rules are added dynamically as well. pls see an an simplified example below of my targeted form:
What is a good structure of javascript code for adding, removing and validate sets of forms fields? I googled -also on this site- and there are many javascript examples for adding sets of formfields. I like the example I found at view-source:http://www.coldfusionjedi.com/demos/jqueryvalidation/testadd.cfm, which uses a form template. But I struggle in particular with the javascript coding for the removing buttons..(which are not in the example)
my targeted (simplified) form (template with 1 set of 3 formfields):
<form name="myForm" id="myForm" method="post" action="">
<input id="name1" name="name1" />
<input id="email1" name="email1" />
<input id="phone1" name="phone1" />
<input type="submit" value="Save">
</form>
I think that you should template the form. I.e. wrap it in a function, so you can create it again and again. Here is a jsfiddle http://jsfiddle.net/krasimir/2sZsx/4/
HTML
<div id="wrapper"></div>
add form
JS
var wrapper = $("#wrapper");
var addForm = $("#add-form");
var index = 0;
var getForm = function(index, action) {
return $('\
<form name="myForm" id="myForm" method="post" action="' + action + '">\
<input id="name' + index + '" name="name' + index + '" />\
<input id="email' + index + '" name="email' + index + '" />\
<input id="phone' + index + '" name="phone' + index + '" />\
<input type="submit" value="Save">\
remove form\
</form>\
');
}
addForm.on("click", function() {
var form = getForm(++index);
form.find(".remove").on("click", function() {
$(this).parent().remove();
});
wrapper.append(form);
});
Simple validation can be done when your form is submitted, thus:
$('#myForm').submit({
var n1 = $('#name1').val();
var e1 = $('#email1').val();
var p1 = $('#phone1').val();
if (n1=='' || e1=='' || p1=='') {
alert('Please complete all fields');
return false;
}
});
Note that the return false will abort the submit and return user to the document.
Great code for adding/removing form fields can be found in this question: https://stackoverflow.com/questions/18520384/removing-dynamically-generated-textboxes-in-jquery
jsFiddle here
If you are using KeenThemes (maybe Metronic theme)
https://preview.keenthemes.com/good/documentation/forms/formvalidation/advanced.html
You can do like this.
var form = document.getElementById('form_id');
var validator = FormValidation.formValidation(
form,
{
fields: {
name: {
validators: {
notEmpty: {
message: 'Please enter template name'
},
stringLength: {
min: 3,
trim: true,
message: 'Please enter a longer name.'
},
}
},
...
more fields here
...
},
plugins: {
trigger: new FormValidation.plugins.Trigger(),
bootstrap: new FormValidation.plugins.Bootstrap(),
},
});
function addNewFieldDynamically() {
// add new field here
...
validator.addField('field_name', {
validators : {...}
})
}
function removeFieldDynamically() {
// remove a field here
...
validator.removeField('field_name')
}
So, instead of having a form in the HTML, I decided to create the form on fly and append it to another element (in my case a <section>, but that will be an option in the near future).
I'm using this method:
var formWrapper = ['<div class="content-login">','</div>'];
var form = [
'<form name="login-form" class="login-form" method="post" action="#">',
'<fieldset class="login-fields">',
'<fieldset class="username-wrapper">',
'<label for="username" class="user-img"><img src="assets/gfx/user.png" alt="Username" /></label>',
'<input type="text" name="username" class="username" placeholder="Username" value="" autocomplete="off" />',
'</fieldset>',
'<fieldset class="password-wrapper">',
'<label for="password" class="pass-img"><img src="assets/gfx/password.png" alt="Password" /></label>',
'<input type="password" name="password" class="password" placeholder="Password" value="" autocomplete="off" />',
'</fieldset>',
'<fieldset class="login-wrapper">',
'<button type="submit" name="login" class="login">Login</button>',
'</fieldset>',
'</fieldset>',
'</form>'
];
setTimeout(function () {
$(formWrapper.join('')).appendTo('section').hide();
$(form.join('')).appendTo('.content-login');
$('.content-login').fadeIn('slow');
}, 1500);
This way I have a nice fade in effect and it will give me the opportunity to change whatever I want after I fully develop it.
But my question is in fact the following: I have a form, so of course I will use Ajax to submit it, and I already have the script for that. The thing is now, when I click on the button, the .click event does not occur, it only takes me to the default action of the form which is "#" in my case. Why is that ?
Here is the other part of the script, for a better understanding :
$('.login-form .login').click(function(){
if($('input.username').val() == "" || $('input.password').val() == "")
{
console.log('Please enter Username & Password');
$('.login-form').effect("shake", { distance: 40, times: 2 }, 100);
return false;
}
else {
$('.login-fields').fadeOut();
$('.login-form').spin("login", "#ffffff");
$.ajax
({
type: 'POST',
url: 'assets/class/login/process.php',
dataType: 'json',
data:
{
username: $('input.username').val(),
password: $('input.password').val()
},
success:function(data)
{
if(!(data.lockdown == true)) {
if(data.error === true) {
console.log(data.message);
$('.login-form').spin(false);
$('.login-fields').fadeIn();
$('.login-form').effect("shake", { distance: 40, times: 2 }, 100);
}
else {
console.log(data.message);
$('.login-form').spin(false);
$('.login-fields').fadeIn();
$('.content-login').fadeOut();
var structure = [
'<div class="after-login">',
'<div class="inside">',
'<div class="row-one">',
'<h1>',data.message,'</h1>',
'</div>',
'<div class="row-two">',
'<a class="cancel" href="',links.cancel,'?logout">Cancel</a>',
'<a class="continue" href="',links.proceed,'">Continue</a>',
'</div>',
'</div>',
'</div>'
];
setTimeout(function () {
$(structure.join('')).appendTo('section').fadeIn('slow');
}, 1500);
}
}
else {
console.log(data.message);
$('.login-form').spin(false);
$('.content-login').fadeOut();
var structure = [
'<div class="system-lockdown">',
'<div class="inside">',
'<div class="row-one">',
'<h1>',data.message,'</h1>',
'</div>',
'<div class="row-two">',
'<a class="back" href="',links.goback,'">Back</a>',
'</div>',
'</div>',
'</div>'
];
setTimeout(function () {
$(structure.join('')).appendTo('section').fadeIn('slow');
}, 1500);
}
},
error:function(XMLHttpRequest,textStatus,errorThrown)
{
console.log('A PHP error triggered this, check your PHP log file for more information');
}
});
return false;
}
});
$.click() will only work on elements that have been created before the handler was created.
Instead, use $.live() instead:
$('.login-form .login').live('click', function() {
// Your code
});
If you're using jQuery 1.7 or above, you can also use $.on() in a similar way:
$('.login-form .login').on('click', function() {
// Your code
});
The preferred way to handle events with dynamically added content is with on()—or delegate, since you're on jQuery 1.6
$(document).delegate('.login-form .login', 'click', function(){
});
Note that this will listen to every single click anywhere in your document. Ideally you'd like to identify some more narrow container from which all clicks will come, and listen to that. So if all these clicks will be coming from your section, you'd do this
$("section").delegate('.login-form .login', 'click', function(){
});