How to pass dynamic value to jquery validation function - javascript

I have a form which have some dynamically added input,
Here i input have total_amt = 100;
How can i, form should not submit until, sum of all the dynamically added inputs must be equal to total_amt
Here is my code.
$(function(){
var i = 1;
$('#add_more').click(function(event) {
event.preventDefault();
$('input.items').last().attr('name', 'item['+i+']');
$('#cart_items').append($('#tmp_cart').html());
$('input[name="item['+i+']"]').rules("add", {
required: true,
depositsSum : function(){
return $(this).val();
},
messages:'Sum of total items should be equal to 100',
});
i++;
});
$.validator.addMethod("depositsSum", function(value, element, params)
{
var amnts = 0;
$(params[0]).each(function() {
amnts += parseFloat($(this).val());
});
return amnts;
});
$("#myForm").validate({
rules: {
'item[0]': {
required:true
}
}
});
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.17.0/jquery.validate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.17.0/additional-methods.min.js"></script>
<form action="" method="POST" id="myForm">
Total Items<input type="text" value="100" name="total_amt" id="total_amt">
<div id="cart_items">
Items<input type="text" name="item[0]" class="items"><br/>
</div>
<button id="add_more">Add More</button>
<input type="submit" name="submit" value="submit">
</form>
<div id="tmp_cart" style="display: none;">
<label>
Items<input type="text" name="item[]" class="items">
</label><br/>
</div>

Two flaws in your code...
Within your .rules() method:
depositsSum : function(){
return $(this).val();
},
You're trying to set the parameter of you custom rule to the value of the field. This is complete nonsense. A parameter is something like Max: 10, where 10 is the parameter and it defines the rule; it's never the actual value of the field, which, by the way, always changes and is empty when the page loads. When you want to invoke the custom rule, set the parameter to true.
And related to the next problem...
Within your .addMethod() method:
$(params[0]).each(function() {
amnts += parseFloat($(this).val());
});
The params argument would be useless in your case, since the parameter can not be used for passing the dynamic values of other fields. Use a jQuery selector to grab the other fields. Since the name begins with item, use the "starts with" selector.
$('[name^="item"]').each(function() {
amnts += parseFloat($(this).val());
});

Related

How get the Count of Empty Input fields?

How can I check the Number of Incomplete Input fields in Particular ID, (form1, form2).
If 2 input fields are empty, in i want a msg saying something like "Incomplete Input 2"
How is it Possible to do this in JS ?
<div id="form1">
<span>Number of Incomplete Input: 2</span>
<input type="text" value="">
<input type="text" value="">
</div>
<div id="form2">
<span>Number of Incomplete Input: 1</span>
<input type="text" value="Test">
<input type="text" value="">
</div>
This is the JS, which is working, i have have multiple JS with class named assigned to each inputs and get the value, but i need to make this check all the Input fields inside just the ID.
$(document).on("click", "#form1", function() {
var count = $('input').filter(function(input){
return $(this).val() == "";
}).length;
alert(count);
});
Your html structure, especially form structure is not correct, so you should first add some submit button to form that can be clicked. Then you can add event listener on form's submission. In the event handler you should select children inputs inside the form tag using $(this).children("input"). Now you can filter them.
$(document).on("submit", "#form1", function (e) {
e.preventDefault();
var count = $(this)
.children("input")
.filter(function (input) {
return $(this).val() == "";
}).length;
alert(count);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="form1">
<span>Number of Incomplete Input: 2</span>
<input type="text" value="">
<input type="text" value="">
<button type="submit">Submit</button>
</form>
This is the JS, which is working, if I have have multiple JS with class named assigned to each inputs and Im getting the value, but i have multiple JS for this to work.
How can i make this Simpler say like, when user clicks on Div, it only checks the input fields inside that div.
$(document).on("click", "#form1", function() {
var count = $('.input_field1').filter(function(input){
return $(this).val() == "";
}).length;
alert(count);
});
HTML
<div id="form1">
<span>Number of Incomplete Input: 2</span>
<input type="text" value="" class="input_field1">
<input type="text" value=""class="input_field1">
</div>
<div id="form2">
<span>Number of Incomplete Input: 1</span>
<input type="text" value="Test" class="input_field2">
<input type="text" value="" class="input_field2">
</div>
See snippet below:
It has commented and if you put some effort on it, you can have a jQuery plugin out of it.
(function () {
'use strict';
var
// this use to prevent event conflict
namespace = 'customValidation',
submitResult = true;
var
input,
inputType,
inputParent,
inputNamePlaceholder,
//-----
writableInputTypes = ['text', 'password'],
checkboxInputType = 'checkbox';
var
errorContainerCls = 'error-container';
// Add this function in global scope
// Change form status with this function
function changeFormStatus(status) {
submitResult = submitResult && status;
}
// Check if a radio input in a
// group is checked
function isRadioChecked(form, name) {
if(!form || !name) return true;
var radio = $(form).find('input[type="radio"][name="' + name.toString() + '"]:checked');
return typeof radio !== 'undefined' && radio.length
? true
: false;
}
function eachInputCall(inp, isInSubmit) {
input = $(inp);
inputType = input.attr('type');
// assume that we have a name placeholder in
// attributes named data-name-placeholder
inputNamePlaceholder = input.attr('data-name-placeholder');
// if it is not present,
// we should have backup placeholder
inputNamePlaceholder = inputNamePlaceholder ? inputNamePlaceholder : 'input';
if(!inputType) return;
// you have three type of inputs in simple form
// that you can make realtime validation for them
// 1. writable inputs ✓
// 2. checkbox inputs ✓
// 3. radio inputs ✕
// for item 3 you should write
// another `else if` condition
// but you should have it for
// each name (it was easier if it was a plugin)
// radio inputs is not good for realtime
// unchecked validation.
// You can check radios through submit event
// let make it lowercase
inputType = inputType.toLowerCase();
// first check type of input
if ($.inArray(inputType, writableInputTypes) !== -1) {
if(!isInSubmit) {
input.on('input.' + namespace, function () {
writableInputChange(this);
});
} else {
writableInputChange(inp);
}
} else if ('checkbox' == inputType) { // if it is checkbox
if(!isInSubmit) {
input.on('change.' + namespace, function () {
checkboxInputChange(this);
});
} else {
checkboxInputChange(inp);
}
}
}
// Check if an input has some validation
// (here we have just required or not empty)
function writableInputChange(inp) {
// I use $(this) instead of input
// to prevent conflict if selector
// is a class for an input
if('' == $.trim($(inp).val())) {
changeFormStatus(false);
// your appropriate message
// you can use bootstrap's popover
// to modefy just input element
// and make your html structure
// more flexible
// or
// if your inputs are in
// separate containers do
// somthing like below
inputParent = $(inp).parent();
if(!inputParent.children('.' + errorContainerCls).length) {
inputParent.append($('<div class="' + errorContainerCls + '" />').text('Please fill ' + inputNamePlaceholder));
}
} else {
changeFormStatus(true);
// I assume we have separate
// containers for each input
inputParent = $(inp).parent();
inputParent.children('.' + errorContainerCls).remove();
}
}
// Check if an checkbox is checked
function checkboxInputChange(chk) {
if(!$(chk).is(':checked')) {
changeFormStatus(false);
// if your inputs are in
// separate containers do
// somthing like below
inputParent = $(chk).parent();
if(!inputParent.children('.' + errorContainerCls).length) {
inputParent.append($('<div class="' + errorContainerCls + '" />').text('Please check ' + inputNamePlaceholder));
}
} else {
changeFormStatus(true);
// I assume we have separate
// containers for each input
inputParent = $(chk).parent();
inputParent.children('.' + errorContainerCls).remove();
}
}
$(function () {
var
form = $('#form'),
// you can change this selector with your classes
formInputs = form.find('> .input-group > input');
formInputs.each(function () {
eachInputCall(this);
});
form.submit(function () {
submitResult = true;
// check all inputs after form submission
formInputs.each(function () {
eachInputCall(this, true);
});
// Because of radio grouping by name,
// we should select them separately
var selectedGender = isRadioChecked($(this), 'gender');
var parent;
if(selectedGender) {
changeFormStatus(true);
parent = $(this).find('input[type="radio"][name="gender"]').parent();
parent.children('.' + errorContainerCls).remove();
} else {
changeFormStatus(false);
// I assume that all radios are in
// a separate container
parent = $(this).find('input[type="radio"][name="gender"]').parent();
if(!parent.children('.' + errorContainerCls).length) {
parent.append($('<div class="' + errorContainerCls + '" />').text('Please check your gender'));
}
}
if(!submitResult) {
console.log('There are errors during validations!');
}
return submitResult;
});
});
})(jQuery);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="form">
<div class="input-group">
<input type="text" name="input1" data-name-placeholder="name">
</div>
<div class="input-group">
<input type="checkbox" name="input2" data-name-placeholder="agreement">
</div>
<div class="input-group">
<input type="radio" name="gender">
<input type="radio" name="gender">
</div>
<button type="submit">
submit
</button>
</form>

Jquery one button updates multiple input fields on form

I am trying to update two input fields in a form when clicking one button. I actually had all the code right when using document.getElementById, but the form that I'm using strips the ID's I set away, so I can't use getbyid. If I know the form field name, how could I change my function to do the same thing? Please note that my form has more than two fields, including a submit button, so I don't want to update those.
This is what I used before (with the ID selector)
Html:
<input type="text" name="field-1" id="info1">
<input type="text" name="field" id="info2">
Populate
JS:
function addTxt(val, id,no)
{
var id = id;
for(var i=1;i<=no;i++){
document.getElementById(id+i).value = val[i-1];
}
}
Fiddle:
http://jsfiddle.net/qwz47phx/3/
Edited with a much simpler and readable approach
function addVal(obj) {
event.preventDefault(); // Prevent page scrolltop on anchor click
$.each(obj, function(k, v) {
$("input[name='"+ k +"']").val( v );
})
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" name="foo">
<input type="text" name="bar">
<a href="#" onclick='addVal({foo:"Hello", "bar-baz":"World"})'>Populate</a>
Or with native JS (ES5+):
function addVal(obj) {
Object.keys(obj).forEach(function(name) {
document.querySelector('input[name="' + name + '"]').value = obj[name];
});
}
<input type="text" name="foo">
<input type="text" name="bar">
<input type="text" name="name-with-dashes">
<a href="#" onclick='addVal({foo:"Hello", bar:"World", "name-with-dashes": "Works !"})'>Populate</a>
If you have problems with IDs you can use querySelector to select inputs by name like this:
JS:
function addTxt(val, id, no) {
for (var i = 1; i <= no; i++) {
document.querySelector('input[name="' + id + i + '"]').value = val[i - 1];
}
}
HTML:
<input type="text" name="info1" id="info1">
<input type="text" name="info2" id="info2">
Populate
Demo: http://jsfiddle.net/iRbouh/qwz47phx/6/
I hope this will help you.
You can use a jQuery attribute= selector to grab by name instead of ID.
function addTxt(val, id,no)
{
for(var i=1;i<=no;i++){
var name = id+i;
$("input[name='"+name+"']").val(val[i-1]);
}
}
Please note that this function will be looking for names of info1, info2, info3, etc, just as your original script did. However, in the HTML, you have names of info and info-1. Either the names will have to be changed to fit the function, or the function can be slightly more intricate.
Fiddle: http://jsfiddle.net/qwz47phx/8/

Sum up all text boxes with a particular class name?

I have a grid, with one of the columns containing a textbox, where a user can type in a dollar amount. The text boxes are declared as:
<input class="change-handled" sub-category-id="83" data-id="" style="text-align: right; width: 100%" type="number" value="">
Some are all decorated with the class "change-handled".
What I need to do, is, using javascript/jquery, sum up all the boxes which are using that class, and display the total elsewhere on the screen.
How can I have a global event, that would allow this to occur when ever I exit one of the boxes (i.e: Tab out, or ENTER out).
At the moment, I have an event which doesn't do much at the moment, which will be used:
$('body').on('change', 'input.change-handled', SaveData);
function SaveData() {
var dataId = $(this).attr('data-id');
var categoryId = $(this).attr('sub-category-id');
var value = $(this).val();
}
How can I use that SaveData event, to find all the editboxes with the 'change-handled' class, sum up their values, and display it somewhere?
In plain JavaScript:
var changeHandled = [].slice.call(document.querySelectorAll('.change-handled'));
var total = document.querySelector('.total');
function calc() {
total.textContent = changeHandled.reduce(function(total, el) {
return total += Number(el.value);
}, 0);
}
changeHandled.forEach(function(el) {
el.onblur = calc;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="number" class="change-handled">
<input type="number" class="change-handled">
<input type="number" class="change-handled">
Total: $<span class="total">0</span>
I think what you're looking for is the blur event.
$('body').on('blur', 'input.change-handled', UpdateTotal);
function UpdateTotal() {
var total = 0;
var $changeInputs = $('input.change-handled');
$changeInputs.each(function(idx, el) {
total += Number($(el).val());
});
$('.total').text(total);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="number" class="change-handled">
<input type="number" class="change-handled">
<input type="number" class="change-handled">
Total: $<span class="total">0</span>
Here's how you can sum up the values:
var total = 0;
$(".change-handled").each(function(index, box) {
total += parseInt($(box).val(), 10);
});
You would then display them by using the text or html functions provided by jQuery on elements.
This can be used from anywhere in your code, including the event handler.

Calculate form inputs onChange

I have a dynamic form that is being generated based on what the user adds to the cart.
For example, the form will looks something like this,
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test Form</title>
</head>
<body>
<form action="" name="cart" id="cart">
<input type="text" name="sku1">
<input type="text" name="sku2">
<input type="text" name="sku3">
<input type="text" name="sku4">
<input type="text" name="sku5">
<div class="sum" id="sum"> Total: {SUM SHOULD SHOW UP HERE)</div>
<button name="submit">Send</button>
</form>
</body>
</html>
But those input fields are generated automatically and may be more or less than 5 fields.
How to calculate those input SUM value and output to SUM div without page refresh?
JavaScript/jQuery?
$('button[name="submit"]').click(function () {
var sum = 0;
$('#cart input[name^="sku"]').each(function () {
var val = isNaN(+this.value) ? 0 : +this.value;
sum += val;
});
$('#sum').text(sum);
});
Or
var inp = $('#cart input[name^="sku"]');
inp.change(function () {
var sum = 0;
inp.each(function () {
var val = isNaN(+this.value) ? 0 : +this.value;
sum += val;
});
$('#sum').text(sum);
});
Attribute Starts With Selector [name^="value"]
.change()
isNaN()
You can use the onsubmit attribute of the form to do whatever you want to before the form gets submitted. You can change action attribute also. You can also preventDefault as said here-
jQuery on submit preventDefault() does not works
You can give the elements a class, amountForTotal, and use a function to calc the total, which you can add to a button, or onchange event of an input.
function calcTotal( $elements ){
var total = 0;
$elements.each(function(){
// if the input has no value, add 0, if it has, add the value
total+= this.value.length===0 ? 0 : parseInt(this.value);
})
return total; // return the total
}
$elements = $('.amountForTotal'); // select them
// Bind an event to recalc the total
$elements.on('keyup', function(){
alert( calcTotal($elements) );
});
In this code I provided the selector as input. This is luxery, not needed, you can add that selector in the function, but this way it can be used more flexible. You can use the [name^=*] selector here, but its slower than a class, which you might notice in large documents.
Also, In my code I check if it has to no value to prevent errors. You can expand this to test if the input is actualy a number.

adjusting default value script to work with multiple rows

I am using a default value script (jquery.defaultvalue.js) to add default text to various input fields on a form:
<script type='text/javascript'>
jQuery(function($) {
$("#name, #email, #organisation, #position").defaultvalue("Name", "Email", "Organisation", "Position");
});
</script>
The form looks like this:
<form method="post" name="booking" action="bookingengine.php">
<p><input type="text" name="name[]" id="name">
<input type="text" name="email[]" id="email">
<input type="text" name="organisation[]" id="organisation">
<input type="text" name="position[]" id="position">
<span class="remove">Remove</span></p>
<p><span class="add">Add person</span><br /><br /><input type="submit" name="submit" id="submit" value="Submit" class="submit-button" /></p>
</form>
I am also using a script so that users can dynamically add (clone) rows to the form:
<script>
$(document).ready(function() {
$(".add").click(function() {
var x = $("form > p:first-child").clone(true).insertBefore("form > p:last-child");
x.find('input').each(function() { this.value = ''; });
return false;
});
$(".remove").click(function() {
$(this).parent().remove();
});
});
</script>
So, when the page loads there is one row with the default values. The user would then start adding information to the inputs. I am wondering if there is a way of having the default values show up in subsequent rows that are added as well.
You can see the form in action here.
Thanks,
Nick
Just call .defaultValue this once the new row is created. The below assumes the format of the columns is precticable/remains the same.
$(".add").click(function() {
var x = $("form > p:first-child");
x.clone(true).insertBefore("form > p:last-child");
x.find('input:not(:submit)').defaultvalue("Name", "Email", "Organisation", "Position");
return false;
});
You should remove ids from the input fields because once these are cloned, the ids, classes, everything about the elements are cloned. So you'll basically end up with multiple elements in the DOM with the same id -- not good.
A better "set defaults"
Personally I would remove the "set defaults plugin" if it's used purely on the site for this purpose. It can easily be re-created with the below and this is more efficient because it doesn't care about ordering of input elements.
var defaults = {
'name[]': 'Name',
'email[]': 'Email',
'organisation[]': 'Organisation',
'position[]': 'Position'
};
var setDefaults = function(inputElements)
{
$(inputElements).each(function() {
var d = defaults[this.name];
if (d && d.length)
{
this.value = d;
$(this).data('isDefault', true);
}
});
};
Then you can simply do (once page is loaded):
setDefaults(jQuery('form[name=booking] input'));
And once a row is added:
$(".add").click(function() {
var x = $("form > p:first-child");
x.clone(true).insertBefore("form > p:last-child");
setDefaults(x.find('input')); // <-- let the magic begin
return false;
});
For the toggling of default values you can simply delegate events and with the help of setDefault
// Toggles
$('form[name=booking]').delegate('input', {
'focus': function() {
if ($(this).data('isDefault'))
$(this).val('').removeData('isDefault');
},
'blur': function() {
if (!this.value.length) setDefaults(this);
}
});
Fiddle: http://jsfiddle.net/garreh/zEmhS/3/ (shows correct toggling of default values)
Okey, first of all; ids must be unique so change your ids to classes if you intend to have more then one of them.
and then in your add function before your "return false":
var
inputs = x.getElementsByTagName('input'),
defaults = ["Name", "Email", "Organisation", "Position"];
for(var i in inputs){
if(typeof inputs[i] == 'object'){
$(inputs[i]).defaultvalue(defaults[i]);
}
}

Categories

Resources