I may just be searching Google using the wrong keywords but I am having very little luck finding information on creating expandable form fields. I have an input form where a user can list all of the inventory assigned to a server node, but would like for them to be able to add additional items if needed. Example being the form shows an option for (1) Disk to be added but they can click a + symbol and add more.
I already created 8 MYSQL rows for each type such as disk1, disk2, etc. to allow for a considerable amount to be stored. However, my concern is that this works out to be a LOT of options.
1) How can I use Javascript to create expandable forms? I only found one code example that didn't work. 2) Should I hard-code all of the options? Such as, right now my code has a Select box named "ram", "motherboard", etc. Could I generate these or should I go ahead and write it out for each field such as "ram1", "ram2", etc?
Cloning the field in JavaScript is easy. Say you have:
<select name="hdd"><!-- ...options here...--></select>
then once you get a reference to that existing element in the DOM (see below), you can do this:
var newSelect = existingSelect.cloneNode(true);
newSelect.selectedIndex = -1; // To clear any existing selection
existingSelect.parentNode.insertBefore(newSelect, existingSelect.nextSibling);
Getting the reference to the existing select
can be done on any modern browser using a CSS selector and document.querySelector
(to get the first match) or document.querySelectorAll
(to get a list of all matches), for instance:
var list = document.querySelectorAll('select[name="hdd"]');
var existingSelect = list[list.length - 1]; // Get the last one
...which will give you the last one. Or more likely, you have a row of some kind (a tr
, or a div
) containing that which you want to copy. Not a problem, give that row a class (say, "hdd"
), and clone the entire thing (here I'm cloning the last row and adding it to the end):
var list = document.querySelectorAll('.hdd');
var existingRow = list[list.length - 1]; // Get the last one
var newRow = existingRow.cloneNode(true); // Clone it
newRow.querySelector('select[name="hdd"]').selectedIndex = -1; // Clear selected value
existingRow.parentNode.insertBefore(newRow, existingRow.nextSibling);
On the MySQL side of things, it's best not to have columns like hdd1
, hdd2
, etc., because it makes queries on those fields complicated and does, of course, limit the maximum number you can have (granted you'll probably want to limit that anyway). (Having those columns in one row is called "denormalizing" the DB.)
The usual way to do that in DB design is to have a second table, listing HDDs, where a key in that second table (a "foreign key") links back to your main table. (See "database normalization" for more information.)
So your main table might have a record id, say SystemID
. Your HDDs table would then have a SystemID
column and an HDD
column, where it could have many rows for the same SystemID
.
Here's a complete example of the form bit: Live Copy | Live Source
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Add Form Field Example</title>
</head>
<body>
<div class="hdd">
<label>HDD: <select name="hdd">
<option>--choose--</option>
<option>80GB</option>
<option>500GB</option>
<option>1TB</option>
<option>2TB</option>
</select></label></div>
<input type="button" id="theButton" value="Add Row">
<script>
(function() {
document.getElementById("theButton").addEventListener("click", addRow, false);
function addRow() {
var list = document.querySelectorAll('.hdd');
var existingRow = list[list.length - 1]; // Get the last one
var newRow = existingRow.cloneNode(true); // Clone it
newRow.querySelector('select[name="hdd"]').selectedIndex = -1; // Clear selected value
existingRow.parentNode.insertBefore(newRow, existingRow.nextSibling);
}
})();
</script>
</body>
</html>
Some useful references: