Cloning a form div

Associate
Joined
19 Jul 2006
Posts
1,847
looking for some help here.
Can only use PHP and javaScript, JQuery for this solution.

I have a form that takes in customer name and address I need the ability to add unlimited customers to this form. eg
PHP:
<?php
$customers = NULL // A collection of customers passed through the controller
    foreach($customers as $customer){
    <div>     
        <label for="customer_<?php echo $i ?>_forename">Customer Forename:</label>
        <input type='text' id="customer_<?php echo $i ?>_forename" name='cust[<?php echo $i ?>][forename]' value="<?php echo $customer->forename; ?>" />
    </div>
}
?>
I need a button that I can click that will render a new form section for the new customer details. so that would basically output

PHP:
<div>     
        <label for="customer_<?php echo $i+1 ?>_forename">Customer Forename:</label>
        <input type='text' id="customer_<?php echo $i+1 ?>_forename" name='cust[<?php echo $i+1 ?>][forename]' value="<?php echo $customer->forename; ?>" />
    </div>

Any tips on how to do this or what I should be googling?

Thanks
 
Give the form field a class you can use to select it based on then use jQuery to find the last occurrence of that class within your form. You can then do a jQuery.clone() on the form field and jQuery.append() it to the form. You'll need to set the input name and any data attributes again so it gets the correct index. I'd also recommend using data- attributes instead of an ID, then you can use jQuery.data() to get and set this for the cloned field.
 
iKettle's solution would work nicely, but wouldn't let you give different customer fields a different ID. If this is a problem, you could always do something like:

Code:
var count = 0;
var fields ="<input type='text' id='customer" + count + "' />

$('.add-customer-button').click(function(){ $('form').append(fields);  count ++; });

Not tested and I have no syntax highlighting so will need tweaking, but if it works and it's stupid...
 
iKettle's solution would work nicely, but wouldn't let you give different customer fields a different ID. If this is a problem, you could always do something like:

Code:
var count = 0;
var fields ="<input type='text' id='customer" + count + "' />

$('.add-customer-button').click(function(){ $('form').append(fields);  count ++; });

Not tested and I have no syntax highlighting so will need tweaking, but if it works and it's stupid...
It would, you would just parse the ID/data-index attribute you have from the previous element and modify the ID of the cloned one with jQuery :)

The downside to putting markup in your JS and not cloning elements from the DOM is you have duplicate versions of the same HTML which both need to be maintained. The count also won't take into consideration any other fields which were already on the page (so not suitable for an edit form)
 
Last edited:
Thanks I have it working in a fashion

it produces things like this
HTML:
<p class="clearfix">
                <label for="cust_2_fname">Customer Forename:</label>
                <input type="text" id="cust_2_fname" name="cust[2][fname]" value="Peter" class="">
                <img src="/assets/admin-icons/nc-b.png" class="" rel="secondary_cust_2_fname_box" width="15px">
            </p>

in my js i have these
Code:
var $presentId = $div.attr("id");
var num = parseInt( $div.attr("id").match(/\d+/g), 10 ) +1;
var $nextCustomer = $div.clone().attr('id', 'customer_details_'+num );
    //clear textboxes
    $nextCustomer.find("input:text").val("");

I need to update my name attr [2] to be [3] and id's from _2_ to be _3_

Something like
$nextCustomer.find("input[name^='cust[$presentId]'").attr('name', 'cust[num]'); // but this isnt working
 
It's the name attribute you need to be concerned with, not id. Name is what is submitted as part of post data.

Also php supports parsing arrays when they are posted as, for example, foo[] so you can sack off any kind of index/counter.

You may also be interested in learning about js templates. Underscore.js has very simple templating.
 
Back
Top Bottom