This is a simple example to reproduce my problem. Basically, I have a form
(to read in data about multiple candidates), in which I have a fieldset
(which takes input of data for one candidate), and then I have a button labelled ADD CANDIDATE
. When it is clicked, the above fieldset
should be cloned and copied below the above fieldset, so that the data about another candidate can be entered.
For the first candidate, each data field in the form
is of the form allCandidatesArray[candidateNumber][fieldName]
, e.g. allCandidatesArray[0][nameInput]
to facilitate the reading and further analysis of data submitted when the form is submitted. So in the Click handler/listener of ADD CANDIDATE
button, I also do some programming to increment the candidateNumber
in allCandidatesArray[candidateNumber][fieldName]
when a new candidate is added.
But the main idea is to clone the previous fieldset
and append the cloned fieldset
below the previous fieldset
. The problem is that the new thing which is appended is Not a fieldset
. It is just three input
elements. No labels, no nothing! What was cloned was a fieldset
containing input
s and label
s.
The question is WHY? And how do I fix this?
$(document).on("click", ".addMobileButton", function() {
//alert(".addMobileButton clicked.");//check
var parentRow = $(this).closest(".row");
var idOfThis = $(this).attr('id');
//alert(idOfThis);//check
//alert(idOfThis.length);//check
var candidateNumber = idOfThis.slice(idOfThis.length-2, idOfThis.length-1);
//alert("candidateNumber: " + candidateNumber);//check
var nthMobileNumberOfThisCandidate = idOfThis.slice(-1);
//alert("nthMobileNumberOfThiscandidate: " + nthMobileNumberOfThiscandidate);//check
var newNthMobileOfThiscandidate = ++nthMobileNumberOfThisCandidate;
//alert("newNthMobileNumberOfThisCandidate: " + newNthMobileOfThisCandidate);//check
parentRow.after('<div id="rowAddedForCandidatesMobile" class="row valign-wrapper"><div class="input-field col l3"><input type="text" id="mobileInput'+candidateNumber+'" class="validate" name="allCandidatesArray['+candidateNumber+'][mobileInput][]"/><label for="mobileInput'+candidateNumber+'">Mobile</label></div><div class="col l1 addMobileButtonWrapper"><a id="addMobileButton'+candidateNumber+''+newNthMobileOfThisCandidate+'" class="btn-floating btn waves-light waves-effect blue white-text addMobileButton"><i class="material-icons">add</i></a></div></div>');
});
$(document).ready(function() {
/*
*
*/
$("a#addNewCandidateButton").on("click", function() {
alert("#addNewCandidateButton clicked.");//check
var previousFieldset = $(this).parent(".row").prevAll("fieldset.wrapper:first");
//alert(previousFieldset[0].outerHTML);//check
var fieldsetToClone = previousFieldset.clone();
//alert(fieldsetToClone[0].outerHTML);//check
var idOfAddMobileButton = fieldsetToClone.find(".addMobileButton").attr('id');
//alert('idOfAddMobileButton: ' + idOfAddMobileButton);
var candidateNumber = idOfAddMobileButton.slice(idOfAddMobileButton.length-2, idOfAddMobileButton.length-1);
//alert("candidateNumber: " + candidateNumber);//check
var candidateNumberIncremented = ++candidateNumber;
//alert('candidateNumberIncremented: ' + candidateNumberIncremented);//check
fieldsetToClone.find('input[type=text]').each(function(index) {
var inputNameAttribute = $(this).attr('name');
//alert('inputNameAttribute: ' + inputNameAttribute);//check
var indexOfFirstOpeningBracket = inputNameAttribute.indexOf('[');
//alert('indexOfFirstOpeningBracket: ' + indexOfFirstOpeningBracket);//check
var indexOfFirstClosingBracket = inputNameAttribute.indexOf(']');
//alert('indexOfFirstClosingBracket') + indexOfFirstClosingBracket;//check
var inputNameAttributeArray = inputNameAttribute.split('');
//alert('inputNameAttributeArray: ' + inputNameAttributeArray);//check
//inputNameAttributeArray.splice(indexOfFirstOpeningBracket, indexOfFirstClosingBracket, candidateNumberIncremented);
var lengthOfCandidate = (indexOfFirstClosingBracket - indexOfFirstOpeningBracket) -1;
//alert('lengthOfCandidate: ' + lengthOfCandidate);//check
inputNameAttributeArray.splice((indexOfFirstOpeningBracket+1), lengthOfCandidate, candidateNumberIncremented);
//alert('inputNameAttributeArray after SPLICING:' + inputNameAttributeArray);//check
inputNameAttributeModified = inputNameAttributeArray.join('');
//alert('inputNameAttributeModified: ' + inputNameAttributeModified);//check
$(this).attr('name', inputNameAttributeModified);
});
fieldsetToClone = fieldsetToClone.prepend('<div class="container"><div class="divider"></div></div>');
fieldsetToClone = fieldsetToClone.find("input[type=text]").val('');
previousFieldset.after(fieldsetToClone);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.99.0/js/materialize.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.99.0/css/materialize.min.css" rel="stylesheet"/>
<form id="credentialsForm" action="" method="get">
<fieldset class="container wrapper">
<div class="row valign-wrapper">
<div class="input-field col l3 offset-l1">
<input type="text" id="nameInput0" class="validate" name="allCandidatesArray[0][nameInput]"/>
<label class="blue-text" for="nameInput0">Name</label>
</div>
<div class="input-field col l3 offset-l1">
<input type="text" id="ssnValueInput0" class="validate" name="allCandidatesArray[0][ssnValueInput]"/>
<label class="blue-text" for="ssnValueInput0">SSN</label>
</div>
</div><!--.row-->
<div class="row valign-wrapper">
<div class="input-field col l3">
<input type="text" id="mobileInput0" class="validate" name="allCandidatesArray[0][mobileInput][]"/>
<label class="blue-text" for="mobileInput0">Mobile</label>
</div>
<div class="col l1 offset-l1 addMobileButtonWrapper">
<a id="addMobileButton00" class="btn-floating btn waves-light waves-effect blue white-text addMobileButton"><i class="material-icons">add</i></a>
</div>
</div><!--.row-->
<!--<div class="container"><div class="divider"></div></div>-->
</fieldset><!--#wrapper-->
<div class="row valign-wrapper">
<a id="addNewCandidateButton" class="btn-flat waves-effect waves-light blue white-text col l2">Add Candidate</a>
</div><!--.row-->
<div class="row" id="submitFormRow">
<div class="col l4 offset-l4">
<button type="submit" class="btn waves-light waves-effect">Add Candidates</button>
</div>
</div><!--.row #s -->
</form>
You are overwriting cloned object in the following statements thus only inputs are appended.
fieldsetToClone = fieldsetToClone.prepend('<div class="container"><div class="divider"></div></div>');
fieldsetToClone = fieldsetToClone.find("input[type=text]").val('');
Use
fieldsetToClone.prepend('<div class="container"><div class="divider"></div></div>');
fieldsetToClone.find("input[type=text]").val('');
$(document).on("click", ".addMobileButton", function() {
var parentRow = $(this).closest(".row");
var idOfThis = $(this).attr('id');
var candidateNumber = idOfThis.slice(idOfThis.length - 2, idOfThis.length - 1);
var nthMobileNumberOfThisCandidate = idOfThis.slice(-1);
var newNthMobileOfThiscandidate = ++nthMobileNumberOfThisCandidate;
parentRow.after('<div id="rowAddedForCandidatesMobile" class="row valign-wrapper"><div class="input-field col l3"><input type="text" id="mobileInput' + candidateNumber + '" class="validate" name="allCandidatesArray[' + candidateNumber + '][mobileInput][]"/><label for="mobileInput' + candidateNumber + '">Mobile</label></div><div class="col l1 addMobileButtonWrapper"><a id="addMobileButton' + candidateNumber + '' + newNthMobileOfThisCandidate + '" class="btn-floating btn waves-light waves-effect blue white-text addMobileButton"><i class="material-icons">add</i></a></div></div>');
});
$("a#addNewCandidateButton").on("click", function() {
var previousFieldset = $(this).parent(".row").prevAll("fieldset.wrapper:first");
var fieldsetToClone = previousFieldset.clone();
var idOfAddMobileButton = fieldsetToClone.find(".addMobileButton").attr('id');
var candidateNumber = idOfAddMobileButton.slice(idOfAddMobileButton.length - 2, idOfAddMobileButton.length - 1);
var candidateNumberIncremented = ++candidateNumber;
fieldsetToClone.find('input[type=text]').each(function(index) {
var inputNameAttribute = $(this).attr('name');
var indexOfFirstOpeningBracket = inputNameAttribute.indexOf('[');
var indexOfFirstClosingBracket = inputNameAttribute.indexOf(']');
var inputNameAttributeArray = inputNameAttribute.split('');
var lengthOfCandidate = (indexOfFirstClosingBracket - indexOfFirstOpeningBracket) - 1;
inputNameAttributeArray.splice((indexOfFirstOpeningBracket + 1), lengthOfCandidate, candidateNumberIncremented);
inputNameAttributeModified = inputNameAttributeArray.join('');
$(this).attr('name', inputNameAttributeModified);
});
fieldsetToClone.prepend('<div class="container"><div class="divider"></div></div>');
fieldsetToClone.find("input[type=text]").val('');
previousFieldset.after(fieldsetToClone);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.99.0/js/materialize.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.99.0/css/materialize.min.css" rel="stylesheet" />
<form id="credentialsForm" action="" method="get">
<fieldset class="container wrapper">
<div class="row valign-wrapper">
<div class="input-field col l3 offset-l1">
<input type="text" id="nameInput0" class="validate" name="allCandidatesArray[0][nameInput]" />
<label class="blue-text" for="nameInput0">Name</label>
</div>
<div class="input-field col l3 offset-l1">
<input type="text" id="ssnValueInput0" class="validate" name="allCandidatesArray[0][ssnValueInput]" />
<label class="blue-text" for="ssnValueInput0">SSN</label>
</div>
</div>
<!--.row-->
<div class="row valign-wrapper">
<div class="input-field col l3">
<input type="text" id="mobileInput0" class="validate" name="allCandidatesArray[0][mobileInput][]" />
<label class="blue-text" for="mobileInput0">Mobile</label>
</div>
<div class="col l1 offset-l1 addMobileButtonWrapper">
<a id="addMobileButton00" class="btn-floating btn waves-light waves-effect blue white-text addMobileButton"><i class="material-icons">add</i></a>
</div>
</div>
<!--.row-->
<!--<div class="container"><div class="divider"></div></div>-->
</fieldset>
<!--#wrapper-->
<div class="row valign-wrapper">
<a id="addNewCandidateButton" class="btn-flat waves-effect waves-light blue white-text col l2">Add Candidate</a>
</div>
<!--.row-->
<div class="row" id="submitFormRow">
<div class="col l4 offset-l4">
<button type="submit" class="btn waves-light waves-effect">Add Candidates</button>
</div>
</div>
<!--.row #s -->
</form>