Reputation: 165
I have this table that adds a row, and it is adding the row; however, when I click a button to show where it adds the row (the current code), it's creating more than one row.
For example, if I click the button that loads the current page 3 times and then I click add row button, it adds 3 rows.
It is this method where it's looking for inputs that is causing the rows to add 3 times:
let inputs = $(this).parent().siblings().find("input[type='text']");
Would anyone know why it's doing this?
Thank you
var globalIndex = 0;
$(document).ready(function() {
// create the original collection of student records.
let arr1 = generateItem();
if (arr1) {
var tr;
tr = $('<tr class="student-row">');
tr.append("<td>" +"<button id='addBtn' type='button' class='btn btn-success addBtn' data-target='#addBtn' style='width:50px'>Add</button>" + "</td>");
tr.append("<td>" + ("<input type='text' class='form-control' style='width:50px' name='name' id='name'>") + "</td>");
tr.append("<td>" + ("<input type='text' class='form-control' style='width:80px' name='email' id='email'>") + "</td>");
tr.append("<td>" + ("<input type='text' class='form-control' style='width:80px' name='phone' id='phone'>") + "</td>");
$('#parentTableBody').append(tr);
// clone that collection into a second array (?)
let arr2 = [...arr1];
// For each member of the student collection, create a table row.
$.each(arr2, function(index, element) {
// createRow() creates the DOM student row.
let myRow = createRow(globalIndex, element);
// Stick that row we just created into the parent table.
$('#parentTableBody').append(myRow);
// Add that student into the actual school info.
// globalIndex++;
});
}
/****
* When the add button is clicked, we first create a new Student object.
* By doing this, we can then re-use the same createRow function we
* used when we created each initial row, thus ensuring the same result.
****/
$("#addBtn").click(function() {
// Get all the text input fields for this form.
let inputs = $(this).parent().siblings().find("input[type='text']");
// Create an empty student object.
let myStudentObj = {};
// Iterate over all the text inputs, and create properties for the student
// Each text input name will become the property name.
inputs.each(function(index, input){
/***
* This is a complicated conversion: as the createRow has been defined to
* expect a Titlecase property (first letter is capitalized), but the input
* names are lower case, we need to retrieve the input name, convert it
* to all lowercase (just to be safe), then convert the first char to upper.
***/
let propName = $(input).prop("name")
.toLowerCase();
propName = propName.replace(propName[0], propName[0].toUpperCase());
// Now, create a property on the object with the proper value.
myStudentObj[propName] = $(input).val();
// And let's also blank that input field, so we can create a new student easily.
$(input).val("");
});
/***
* A little more funkiness: the index is the object's position in an array, or list.
* As we have been adding the records sequentially, the number of rows is the index
* of the last row. Adding one to that will give us the index of the current student.
***/
let myStudentIndex = $("#parentTableBody tr.student-row").length,
// And we can create that DOM fragment, as we did when we initialized the list above.
myRow = createRow(myStudentIndex, myStudentObj);
// add our newly created DOM fragment to the parent container.
$("#parentTableBody").append(myRow);
});
});
function generateItem() {
var kids = [{
Name: "Gina",
Email: "[email protected]",
Phone: "211-456-1234",
Edu: [{
School: "college",
Grade: "Freshmen",
Job: "Student",
Martial: "S",
ETC: " "
},
{
School: "college2",
Grade: "Freshmen2",
Job: "Student2",
Martial: "S2",
ETC: "2"
},
{
School: "college3",
Grade: "Freshmen3",
Job: "Student3",
Martial: "S3",
ETC: "3"
}
]
},
{
Name: "Mark",
Email: "[email protected]",
Phone: "144-411-2312",
Edu: [{
School: "highschool",
Grade: "senior",
Job: "cashier",
Martial: "S",
ETC: "honors"
}]
},
{
Name: "Jake",
Email: "[email protected]",
Phone: "333-211-1111",
Edu: [{
School: "highschool",
Grade: "junior",
Job: "waiter",
Martial: "S",
ETC: "honors"
}]
}
];
return kids;
}
/****
* createRow() -- create the student row DOM fragment.
* index = the student index
* obj = the student object, formatted like:
* obj = { Name: "name", Email: "email", Phone: "555-555-5555", <other optional fields>}
*
* returns a td DOM node containing the student info.
****/
function createRow(index, obj) {
// console.log(obj);
globalIndex++;
tr = $('<tr class="student-row">');
tr.append("<td>" + "<button id='modalBtn " + globalIndex + "' type='button' class='btn btn-info' data-toggle='modal' data-target='#myModal'>Info</button>" +
"</td>");
tr.append("<td>" + (obj.Name || "") + "</td>");
tr.append("<td>" + (obj.Email || "") + "</td>");
tr.append("<td>" + (obj.Phone || "") + "</td>");
return tr;
}
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" />
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.bundle.min.js"></script>
<table id="parentTable">
<thead>
<tr class="category">
<th></th>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
</tr>
</thead>
<tbody id="parentTableBody">
</tbody>
</table>
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-body">
<h3>Info</h3>
<div class="well well-sm overflow-auto">
<table class="table table-striped table-hover table-condensed" id="schoolTable">
<thead>
<tr>
<th>School</th>
<th>Grade</th>
<th>Job</th>
<th>Martial</th>
<th>Etc</th>
</tr>
</thead>
<tbody id="schoolModalBody">
</tbody>
</table>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-info" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
Upvotes: 1
Views: 1064
Reputation: 760
From the way you describe the test scenario it looks like for each time you load the page, 1 more row is being added to the table. This could have to do with the following line of code:
$("#addBtn").click(function() { ... }
Everytime you load the page, another 'click' handler is added to your DOM element. This means the third time you load the page, 3 event hanlders are added. You should only add these event handlers once or remove all previous event handlers before adding another one. I found the best solution in a different post: jQuery click events firing multiple times
$(".bet").unbind().click(function() {
//Stuff
});
Upvotes: 1