jQuery solution to the add ingredient row problem
January 4, 2009 – 7:28 pmDue to the fact that I could not find a reasonable solution within the CakePHP framework to add a new row of ingredient list inputs to recipe form I solved the problem using jQuery.
This is the script.
$('#add_ingredient_row').click(function() { // Clone the last row of the table. var clonedRow = $("#ingredient_list tr:last").clone(); // Generate an incremented index for the new row. -1 because there is a table header row var newIndex = (document.getElementById('ingredient_list').rows.length -1); // Set the ID of the row with the new index clonedRow[0].id = 'ingredient_' + newIndex; //console.log('ingredient_' + newIndex); // Loop through all of the inputs and select in the cloned row // Find the name and ID of the input/select element and find the number in it abd replace it with the // new index. $.each($('input, select', clonedRow), function(i, val) { //console.log(val); //console.log('Index -1: ' + (newIndex -1) + '. Index: ' + newIndex); val.name = val.name.replace((newIndex - 1), newIndex); val.id = val.id.replace((newIndex - 1), newIndex); val.value = ''; }); // put the row into the table $("#ingredient_list").append(clonedRow); } );
This is the table that it operates on.
<table id="ingredient_list"> <tr> <th>Amount</th> <th>Measurement Type</th> <th>Description</th> <th>Ingredient</th> </tr> <tr id="ingredient_0"> <td> <div class="input text"><input name="data[IngredientList][0][amount]" type="text" maxlength="5" value="" id="IngredientList0Amount" /></div><input type="hidden" name="data[IngredientList][0][id]" value="" id="IngredientList0Id" /> </td> <td> <select name="data[IngredientList][0][measurement_type_id]" id="IngredientList0MeasurementTypeId"> <option value=""></option> <option value="0000000002">cup</option> <option value="0000000005">fluid ounce</option> <option value="0000000001">ounce</option> <option value="0000000004">tablespoon</option> <option value="0000000003">teaspoon</option> </select> </td> <td> <div class="input text"><input name="data[IngredientList][0][description]" type="text" maxlength="255" value="" id="IngredientList0Description" /></div> </td> <td> <select name="data[IngredientList][0][ingredient_id]" id="IngredientList0IngredientId"> <option value=""></option> <option value="0000000006">broccoli</option> <option value="0000000008">garlic</option> <option value="0000000009">olive oil</option> <option value="0000000010">peanut oil</option> <option value="0000000012">red onion</option> <option value="0000000007">white onion</option> <option value="0000000011">yellow onion</option> </select> </td> </tr> </table>
Here is the final solution I came up with. I abstracted out the cloning and manipulation code into a separate function so that it would be DRY.
$(document).ready(function() { $('#add_recipe_row').click(function() { add_row('recipes_table', 'menu_item_'); }); $('#add_ingredient_row').click(function() { add_row('ingredient_list', 'ingredient_'); } ); }); // ends document.ready function add_row(tableID, rowIDprefix) { // Clone the last row of the table. var clonedRow = $('#'+ tableID + ' tr:last').clone(); // Generate an incremented index for the new row. -1 because there is a table header row var newIndex = (document.getElementById(tableID).rows.length -1); // Set the ID of the row with the new index clonedRow[0].id = rowIDprefix + newIndex; //console.log('ingredient_' + newIndex); // Loop through all of the inputs and select in the cloned row // Find the name and ID of the input/select element and find the number in it abd replace it with the // new index. $.each($('input, select', clonedRow), function(i, val) { //console.log(val); //console.log('Index -1: ' + (newIndex -1) + '. Index: ' + newIndex); val.name = val.name.replace((newIndex - 1), newIndex); val.id = val.id.replace((newIndex - 1), newIndex); val.value = ''; }); // put the row into the table $('#' + tableID).append(clonedRow); }