Reputation: 235
I'm trying to build a page with a few task lists. For this part, I want to use dynamic input fields. The form is being looped by a foreach, which looks to the number of users.
The problem now is that the tags (add, remove and reset) are not working except at the "first loop". And when I click on the on the first loop value, a field will be added at all the "loops", instead of only the first loop.
My PHP Code:
<?php
foreach (glob(/*user as file*/) as $filename) {
echo '
<div class="col-md-4 taskblock">
<img class="taskimage" src="../../../'.$filename.'"/>
<div class="name">User</div>
<div class="dynamic-form">
<a id="add">Add</a> | <a id="remove">Remove</a> | <a id="reset">Reset</a>
<form>
<div class="inputs">
<div><input name="dynamic[]" class="field" value="1" type="text"></div>
</div>
<input name="submit" class="submit" value="Submit" type="button">
</form>
</div>
</div>
';
}
?>
And my Script:
$(document).ready(function(){
var i = $('input').size() + 1;
$('#add').click(function() {
$('<div><input type="text" class="field" name="dynamic[]" value="' + i + '" /></div>').appendTo('.inputs');
i++;
});
$('#remove').click(function() {
if(i > 1) {
$('.field:last').remove();
i--;
}
});
$('#reset').click(function() {
while(i > 2) {
$('.field:last').remove();
i--;
}
});
// here's our click function for when the forms submitted
$('.submit').click(function(){
var answers = [];
$.each($('.field'), function() {
answers.push($(this).val());
});
if(answers.length == 0) {
answers = "none";
}
alert(answers);
return false;
});
});
Upvotes: 2
Views: 1215
Reputation: 4409
Multiple things to fix here.
id
vs class
An id
property must be unique in a document. This is the reason add
, remove
and reset
only affect the first item. We must change them to class
.
<a class="add">Add</a> | <a class="remove">Remove</a> | <a class="reset">Reset</a>
Because you are using var i = $('input').size() + 1;
, you are actually counting both the text fields and the submit buttons. As such, If you have 3 items and add a text field, it will be populated with the value 7
instead of 4
. We must limit the counting to text fields by targeting them with their class .field
:
var i = $('input.field').size() + 1;
Because you use appendTo('.inputs');
, you add a new text field to all items as they each have that element. You must limit the addition to the current item.
To achieve this, we make use of the this
keyword, which will return the add
element that triggered the event. From there, we reach the parent element, look for the .inputs
element within it, then we inject the new element into it.
$(this).parent().find('.inputs')
.append('<div><input type="text" class="field" name="dynamic[]" value="'
+ i + '" /></div>');
That same basic logic must be applied to remove
, but for reasons explained in the next part, we will do something slightly different:
var field = $(this).parent().find('.field:gt(0):last')
i -= field.length;
field.remove();
Because the variable i
is common to all items, its value is always larger than the number of text fields found in any item. Using reset will simply remove all text fields. Instead we must remove all fields except the first from the current item and alter i
by subtracting the number of fields we remove.
We select all the fields except the first using the :gt()
selector, subtract the number of returned fields from i
and then remove the fields.
var fields = $(this).parent().find('.field:gt(0)');
i -= fields.length;
fields.remove();
A demo in available in this JSFiddle.
I'm also not quite sure about the purpose of the variable i
and would promptly ditch it, due to its global nature.
Upvotes: 1