Jquery - Variable not updating into another variable - javascript

first of all i'm not a programmer of any kind, so i please need you to fix my issue.
I have a contact form which have inside a place where i can add more input fields till a maximum of 10.
Each field i add it has inside the code a class that i called "pers", and i want that this class pers has an incremental number near to it, as pers1, 2, 3 and so go on.
Getting the incremental value was easy but the problem is that the class "pers" wont update the variable keeping the first number on document load.
Here is the code
<script type="text/javascript">
window.s = 1;
</script>
<script type="text/javascript">
$(document).ready(function() {
var addButton = $('.add_button');
var wrapper = $('.field_wrapper');
var maxField = 10;
var fieldHTML = '<div style="margin-top:5px;"><input type="text3" name="pers' + window.s + '" placeholder="Nome e Cognome"/><input type="time" style=margin-left:3.5px; autocomplete="off"><input type="time" style=margin-left:3.5px; autocomplete="off"><img src="IMG/less_icon.png"></div>';
$(addButton).click(function() {
if (window.s < maxField) {
window.s++; //Increment field counter
$(wrapper).append(fieldHTML); //Add field html
}
});
$(wrapper).on('click', '.remove_button', function(e) {
e.preventDefault();
$(this).parent('div').remove(); //Remove field html
s--; //Decrement field counter
});
});
</script>
There is a global variable "window.s" because it was my last try to get the var updated.
The fields adds correctly till 10 as it should be, but the "window.s" or when it was only "s" still keeps his first value of 1, and so "pers" is always "pers1". I thought that exposing a global variable i would have fix the problem, but nothing.
What am i doing wrong?
Thank you very much for your help guys.

The problem with your code is because you only set fieldHTML once, when the page loads. At this point window.s is 1, so this is the value that's used every time you reference fieldHTML. The quick fix to this would be to put the fieldHTML definition inside the click() event handler.
However the better approach it to entirely remove the need for the incremental variable at all. Use the same name on all the fields you dynamically generate. This way you don't need to maintain the count (eg. if there have been 5 added and someone deletes the 3rd one, you'll currently end up with 2 per5 elements). Because of this it also simplifies the JS logic. In addition you should put the HTML to clone in a <template> element, not the JS, so that there's no cross-contamination of the codebase.
Here's a working example of the changes I mention:
jQuery($ => {
var $addButton = $('.add_button');
var $wrapper = $('.field_wrapper');
var maxFields = 10;
var fieldHTML = $('#field_template').html();
$addButton.click(() => {
if ($('.field_wrapper > div').length < maxFields) {
$wrapper.append(fieldHTML);
}
});
$wrapper.on('click', '.remove_button', e => {
e.preventDefault();
$(e.target).closest('div').remove();
});
});
.field_wrapper>div {
margin-top: 5px;
}
.field_wrapper input.time {
margin-left: 3.5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<button class="add_button">Add</button>
<div class="field_wrapper"></div>
<template id="field_template">
<div>
<input type="text3" name="pers[]" placeholder="Nome e Cognome" />
<input type="time" name="time1[]" class="time" autocomplete="off" />
<input type="time" name="time2[]" class="time" autocomplete="off" />
<a href="#" class="remove_button" title="Rimuovi">
<img src="IMG/less_icon.png">
</a>
</div>
</template>
You can then receive all the input values as an array in your PHP code, like this.

It's because you have not used the updated value there.
First, you assign a value to window.s, and then you create a variable that uses the value of window.s from the initial state, and on each addition, it just appends the same fieldHtml. So, you are getting the same value.
Here is the answer, you are looking:
<div><button class="add_button">click me</button></div>
<div class="field_wrapper"></div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script type="text/javascript">
window.s = 1;
</script>
<script type="text/javascript">
$(document).ready(function() {
var addButton = $('.add_button');
var wrapper = $('.field_wrapper');
var maxField = 10;
$(addButton).click(function() {
if (window.s < maxField) {
window.s++; //Increment field counter
let fieldHTML = generateLine(window.s);
$(wrapper).append(fieldHTML); //Add field html
}
});
$(wrapper).on('click', '.remove_button', function(e) {
e.preventDefault();
$(this).parent('div').remove(); //Remove field html
s--; //Decrement field counter
});
});
function generateLine(lineNumber){
return '<div style="margin-top:5px;"><input type="text3" name="pers' + lineNumber + '" placeholder="Nome e Cognome"/><input type="time" style=margin-left:3.5px; autocomplete="off"><input type="time" style=margin-left:3.5px; autocomplete="off"><img src="IMG/less_icon.png"></div>';
}
</script>

Related

Generate Dynamic Inputs with Unique Names in jQuery

In my HTML form, it's possible to add additional inputs dynamically by clicking a button. I've got this part to work, however I need each input to have a unique name.
This is my code so far,
<div class="control-group field_wrapper">
<label class="control-label"><strong> Phone Number 1</strong></label>
<input type="text" class="input-medium" name="phone_number[]">
<button class="btn btn-success add-number" type="button" title="Add">Add</button>
</div>
<div class="additionalNumber"></div>
My JS as below,
$(document).ready(function(){
var maxField = 10;
var addButton = $('.add-number');
var wrapper = $('.additionalNumber');
function fieldHTML(inputNumber) {
return `<div class="control-group field_wrapper">\
<label class="control-label"><strong> Phone Number ${inputNumber}</strong></label>\
<input type="text" class="input-medium" name="phone_number[${inputNumber}]">\
<button class="btn btn-danger remove" type="button">Remove</button>\
</div>`;
}
var x = 1;
$(addButton).on('click', function(e) {
if (x < maxField) {
x++;
$(wrapper).append(fieldHTML(x));
}
if (x >= maxField) {
alert('Limited to 10.');
}
});
$(wrapper).on('click', '.remove', function(e) {
e.preventDefault();
$(this).parents('.control-group').remove();
x--;
});
});
Using this code, I can get unique name for each input which are created by dynamically. But my problem is name[x] index not works properly when it is removing. That mean, just think I have added 3 input and delete second one and again I am adding new one, then it has same name twice. In this case, it is phone_number[3] for second input and phone_number[3] for thirt one also.
This is the fiddle from above code. Any help is appreciated.
You don't need to index the inputs for PHP either - 3x inputs named phone_number[] will automatically be indexed 0 - 2 on the back end:
<input type="text" name="phone_number[]">
<input type="text" name="phone_number[]">
<input type="text" name="phone_number[]">
[phone_number] => Array
(
[0] => a
[1] => b
[2] => c
)
That doesn't help with your plain text Phone Number n label though. And maybe you have your own reasons to want an input name index.
If you think about it, if you're going to allow deletions of any item in the list, and you need the results to be sequential, the only option is to renumber everything each time you make a change. You don't need to include any numbering when you add a new element, just regenerate all numbering.
Here's a working snippet doing that. My changes:
No need to pass the count x to fieldHTML(), we're going to renumber everything after you add the element;
Add a <span class='count'></span> in your label, which we can target and update;
Add a reNumber() function which will iterate over all inputs on the page and number them sequentially;
Call that function after any change;
Notes:
The 2 separate tests if (x < maxField) and if (x >= maxField) can be combined into a single if/else;
If you want to get rid of the duplication of your HTML block, you could give the first one an id like template, and then instead of duplicating that HTML in your JS, just copy the template, eg :
let $copy = $('#template').clone();
wrapper.append($copy);
wrapper and addButton are already jQuery objects, no need to wrap them with $() a second time to use them;
If you do want to number your input names, for consistency the first should probably be phone_number[1];
$(document).ready(function() {
var x = 1;
var maxField = 10;
var addButton = $('.add-number');
var wrapper = $('.additionalNumber');
function fieldHTML() {
return `<div class="control-group field_wrapper">\
<label class="control-label"><strong> Phone Number <span class='count'></span></strong></label>\
<input type="text" class="input-medium" name="phone_number[]">\
<button class="btn btn-danger remove" type="button">Remove</button>\
</div>`;
}
/**
* Iterate over all inputs and renumber sequentially
*/
function reNumber() {
let count;
wrapper.find('.field_wrapper').each(function (i) {
// .each() index is 0-based, and input #1 is already on the page,
// so extras start at #2
count = i + 2;
$('.count', $(this)).html(count);
// If you want to index your input names, but you can safely leave
// this out, PHP will index them anyway
$('input', $(this)).attr('name', 'phone_number[' + count + ']')
});
}
addButton.on('click', function(e) {
if (x < maxField) {
x++;
wrapper.append(fieldHTML());
reNumber();
} else {
alert('Limited to 10.');
}
});
wrapper.on('click', '.remove', function(e) {
e.preventDefault();
$(this).parents('.control-group').remove();
x--;
reNumber();
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="control-group field_wrapper">
<label class="control-label"><strong> Phone Number 1</strong></label>
<input type="text" class="input-medium" name="phone_number[]">
<button class="btn btn-success add-number" type="button" title="Add">Add</button>
</div>
<div class="additionalNumber"></div>

Unique name for Add More input

I am trying to create an add more button which will create a new input field. However, I would like to have an unique name set for it.
I tried to search up for an answer, but this does not answer my question.
So, basically what I tried to make my namefield unique is to use the php method rand(). The concept is that - when the add more button is clicked, it will have a name attached to the number given to me by rand().
However, what happens is that it takes the value generated by rand() and applies it to all the names of all the inputs generated.
This is my code and what I tried:
HTML:
<div class="field_wrapper">
<div>
<input type="text" name="field_name[<?php echo rand(); ?>]" value=""/>
Add More
</div>
</div>
JQUERY / JAVASCRIPT:
<script type="text/javascript">
$(document).ready(function(){
var maxField = 100; //Input fields increment limitation
var addButton = $('.add_button'); //Add button selector
var wrapper = $('.field_wrapper'); //Input field wrapper
var fieldHTML = '<div><input type="text" name="field_name[<?php echo rand(); ?>]" value=""/>Remove</div>'; //New input field html
var x = 1; //Initial field counter is 1
//Once add button is clicked
$(addButton).click(function(){
//Check maximum number of input fields
if(x < maxField){
x++; //Increment field counter
$(wrapper).append(fieldHTML); //Add field html
}
});
//Once remove button is clicked
$(wrapper).on('click', '.remove_button', function(e){
e.preventDefault();
$(this).parent('div').remove(); //Remove field html
x--; //Decrement field counter
});
});
</script>
As you can see, the first field generates the number as intended. If you click on the add more, the second field does create an unique number. However, if you click add more once again, the third field copies the same name as the 2nd field.
How do I go about achieving what I want and why is rand() not generating a new code?
Also, does rand() guarantee me that it will be an unique ID or is there a chance for it to repeat the same number?
If it does repeat, then what would be the best approach to take to make it as unique as possible?
If you generate random name with PHP it is done once on the server. Your JS code then copies the same element. What you need is to generate unique names with js.
Avoid random if you can, theoretically, you can hit the same number and run into mysterious bugs.
var generateField = function(name)
{
return '<div><input type="text" name="'+name+'" value=""/>Remove</div>'; //New input field html
}
//Once add button is clicked
$(addButton).click(function(){
//Check maximum number of input fields
if(x < maxField){
x++; //Increment field counter
$(wrapper).append(generateField('field_name['+x+']' ) ); //Add field html
}
});
Random does not necessarily mean unique, even if collisions would be extremely rare. This solution simply increments a totalFieldsCreated variable to get the next unique number (up to the maximum value JavaScript can provide.)
The new fields are created dynamically instead of using a fixed string of HTML. (This technique is more flexible.)
$(document).ready(function() {
// Defines global identifiers
let
currentFieldCount = 1,
totalFieldsCreated = 1;
const
maxFieldCount = 100,
addButton = $('.add_button'),
wrapper = $('.field_wrapper');
// Calls `addField` when addButton is clicked
$(addButton).click(addField);
// Executes anonymous function when `Remove` is clicked, which removes
// the parent div, and decrements (and logs) `currentFieldCount`
$(wrapper).on('click', '.remove_button', function(e) {
e.preventDefault();
$(this).parent('div').remove();
currentFieldCount--;
console.log(`currentFieldCount: ${currentFieldCount}`);
});
// Defines the `addField` function
function addField(){
// Makes sure that `currentFieldCount` and `totalFieldsCreated`
// are not at maximum before proceeding
if(
currentFieldCount < maxFieldCount &&
totalFieldsCreated < Number.MAX_VALUE
){
// Creates an input element, increments `totalFieldsCreated`,
// and uses the incremented value in the input's `name` attribute
const input = document.createElement("input");
input.type = "text";
input.name = "field" + ++totalFieldsCreated;
input.value = "";
// Creates an anchor element with the `remove_button` class
const a = document.createElement("a");
a.href = "javascript:void(0);";
a.classList.add("remove_button");
a.title = "remove";
a.innerHTML = "Remove";
// Adds the new elements to the DOM, and increments `currentFieldCount`
const div = document.createElement("div");
div.appendChild(input);
div.appendChild(a);
$(wrapper).append(div);
currentFieldCount++;
// Logs the new values of both variables
console.log(
`currentFieldCount: ${currentFieldCount},`,
`totalFieldsCreated ${totalFieldsCreated}`
);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="field_wrapper">
<div>
<input type="text" name="field1" value="" />
Add More
</div>
</div>
Try Math.random() in js rather than rand() in php ,Math.floor(Math.random()*90000) + 10000 will generate a five digit random number , Hope this helps
$('.rand').attr('name',"fields["+Math.floor(Math.random()*90000) + 10000+"]")
$('.add_button').click(function(e){
$('.field_wrapper').append('<div><input type="text" name=fields['+Math.floor(Math.random()*90000) + 10000+'] value=""/>Remove</div>')
})
$(document).on('click','.remove_button',function(e){
$(this).parent().remove()
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<div class="field_wrapper">
<div>
<input type="text" class="rand" value=""/>
Add More
</div>
</div>

datepicker used in textbox inside script

when I use date picker in text box outside script it works fine, iwhich looks like this.
<input type="text" id="entry_date" name="entry_date[]" class="form-control datepicker" data-date-format="<?= config_item('date_picker_format'); ?>" value=""/>
But when I use same date picker function inside script it's not working and I don't know whether it will work like this what the way I gave.Here is my code
<script type="text/javascript">
$(document).ready(function () {
$(function () {
$("#datepicker1").datepicker();
});
var maxField = 10; //Input fields increment limitation
var addButton = $('.add_button'); //Add button selector
var wrapper = $('.field_wrapper'); //Input field wrapper
var fieldHTML = '<div class="form-group"><input class="form-control date_pick datepicker col-lg-2" id="datepicker1" placeholder="yyyy-mm-dd" type="text" name="entry_date[]" value=""/></div>'; //New input field html
var x = 1; //Initial field counter is 1
$(addButton).click(function(){ //Once add button is clicked
if(x < maxField){ //Check maximum number of input fields
x++; //Increment field counter
$(wrapper).append(fieldHTML); // Add field html
}
});
});
</script>
Can You please explain to me howI should call this date picker?
Thank You
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.6.4/js/bootstrap-datepicker.min.js"></script>
<button class="add_button">Add</button>
<div class="field_wrapper"></div>
<script type="text/javascript">
$(document).ready(function () {
var maxField = 10; //Input fields increment limitation
var addButton = $('.add_button'); //Add button selector
var wrapper = $('.field_wrapper'); //Input field wrapper
var fieldHTML = ''; //New input field html
var x = 1; //Initial field counter is 1
$(addButton).click(function(){ //Once add button is clicked
if(x < maxField){ //Check maximum number of input fields
x++; //Increment field counter
fieldHTML = '<div class="form-group"><input class="form-control date_pick datepicker col-lg-2" id="datepicker' + x + '" placeholder="yyyy-mm-dd" type="text" name="entry_date[]" value=""/></div>';
$(wrapper).append(fieldHTML); // Add field html
$("#datepicker" + x).datepicker();
}
});
});
</script>
Check html appended properly, or put html code separate to jquery, maybe using jquery code appended lately when datepicker function work.
Regards,

Javascript - prevent onclick event from being attached to all elements with same class

I'm working on a simple form that includes an input field where the user will fill in the required amount by clicking the incrementor/decrementor. The form is created based on data pulled dynamically from the database
Below is the problematic part: html and the jquery handling it:
The incrementor, decrementor and the input field:
-
<input type="text" id="purchase_quantity" class = "purchase_quantity" min="1" max="6" delta="0" style = "width: 32px;" value="1">
+
and the jquery handling the above:
jQuery(function ($) {
$('.addItem').on('click', function () {
var inputval = $(this).siblings('.purchase_quantity').val();
var num = +inputval;
num++;
if(num>6)num=6;
console.log(num);
$(".purchase_quantity").val(num);
return false;
});
$('.removeItem').on('click', function () {
var inputval = $(this).siblings('.purchase_quantity').val();
var num = +inputval;
num--;
if(num<1)num=1;
console.log(num);
$(".purchase_quantity").val(num);
return false;
});
});
Now, what's happening is: onclick of the incrementor/decrementor (+ and -) the value on the input field changes across all the fields in the page instead of the one clicked only. Have spent quite some time on this with no success and will appreciate some help
The line
$(".purchase_quantity").val(num);
says, literally, to change the value on all the fields. Earlier you used
$(this).siblings('.purchase_quantity').val()
to get the value, so why not also use
$(this).siblings('.purchase_quantity').val(num)
to set it?
That's because siblings will get you all items on the same level.
Get the siblings of each element in the set of matched elements,
optionally filtered by a selector.
Place them in separate div elements, and adjust your setter to actually only update the siblings inside that div.
jQuery(function ($) {
$('.addItem').on('click', function () {
var inputval = $(this).siblings('.purchase_quantity').val();
var num = +inputval;
num++;
if(num>6)num=6;
console.log(num);
$(this).siblings('.purchase_quantity').val(num);
return false;
});
$('.removeItem').on('click', function () {
var inputval = $(this).siblings('.purchase_quantity').val();
var num = +inputval;
num--;
if(num<1)num=1;
console.log(num);
$(this).siblings('.purchase_quantity').val(num);
return false;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
-
<input type="text" id="purchase_quantity2" class = "purchase_quantity" min="1" max="6" delta="0" style = "width: 32px;" value="1">
+
</div>
<div>
-
<input type="text" id="purchase_quantity1" class = "purchase_quantity" min="1" max="6" delta="0" style = "width: 32px;" value="1">
+
</div>
you should change $(".purchase_quantity").val(num) to $("#purchase_quantity").val(num)

Increment input field value with jQuery

I want every time when user enter number ,print the new one + old one in console
here is html script
<input type="number"value=""/>
<button>click</button>
my jquery code
$("button").click(function (){
var x = $("input").val();
x+=x;
console.log(x);
});
You have to initialize the value outside somewhere to keep its state.
html
<input type="number" id="inp" value=""/>
<button>click</button>
js
var x = 0;
$("button").click(function (){
var y = parseInt($("#inp").val());
x+=y;
console.log(x);
});
hope this will help to you. refer the working demo.
var thevalue = 0;
$("#click").click(function(){
$("#display").text("The Value is :");
var theinput_value = parseInt($("#num").val());
thevalue += theinput_value;
$("#display").append(thevalue);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Enter the nubmer : <input type="number" id="num"><button id="click">Click on me !</button>
<br>
<p id="display">The Value is :</p>
You just need to make sure x is a global variable so you can save it's value and used each time the click handler is triggered.
I added input casting to avoid string concatenation when using the addition assignment operator.
var x = 0;
$("button").click(function (){
// Get the input
var current_input = parseInt($("input").val());
// If input is not a number set it to 0
if (isNaN(current_input)) current_input = 0;
// Add the input to x
x+=current_input;
// Display it
console.log(x);
});

Categories

Resources