ChronoEngine.com homepage

FAQs

How can I have a button to add more form inputs?

Written
It's quite common on a form to have one part that repeats several times. If the number of repeats varies then it can be useful to have an 'Add one' button that will add an extra copy of this part of the form. An example might be for a booking form where one booking can be for several people and you want to enter all of their names. This FAQ shows you how to do this when the number of repeats is limited e.g. up to x people.
The example described here was written for a specific case where the is a minimum of one person and a maximum of five and there are inputs for 'name' and 'address'. The code is flexible and can easily be amended for a different number of people, or for different inouts.
You can see a demonstration form using CFv4 by clicking {rokbox text=|here|}http://greyhead.org/index.php?option=com_chronoforms&tmpl=component&chronoform=test_form_addafew{/rokbox}. (The layout is a bit crunched in the modal window :-( )
The form inputs are built using PHP in a Custom Element element in the Form Wizard preview box (you need the Normal Wizard to do this, not the Easy Wizard).
<?php
// set the total count
$count = 5;
for ( $i = 1; $i <= $count; $i++ ) {
  // add classes which will let us identify the inputs to hide
  if ( $i == 1 ) {
    $class = 'show_me';
  } else {
    $class = 'hide_me';
  }
  // add the 'Add one' buttons (but not to the last set)
  if ( $i < $count ) {
    $j = $i+1;
    $button = "<div><input type='button' name='addone_{$j}' id='addone_{$j}' value='Add one' class='add_one' /></div>";
  } else {
    $button = "";
  }
  // add the inputs with a little ChronoForms styling
  echo "<div id='recipient_{$i}' class='{$class}' >
  <div class='multiline_start'>
    <label>Name</label>
    <input type='text' name='recipient[{$i}][name]' id='recipient_{$i}_name' />
  </div>
  <div class='multiline_add'>
    <label>Address</label>
    <input type='text' name='recipient[{$i}][address]' id='recipient_{$i}_address' />
  </div>
  <div class='clear' ></div>
  {$button}
</div>";
}
?>
In this case the Pure code box is not checked so that the ChronoForms wrapping divs and CSS are applied. The Label box is left empty.
The second part of the code is JavaScript added in a Load JS action in the On Load event of the form:
window.addEvent('domready', function() {
  // hide all but the first set
  $$('div.hide_me').each(function(el) {
    el.setStyle('display', 'none');
  });
  // call the addOne function passing the row number  
  $$('input.add_one').each(function(el) {
    el.addEvent('click', function(event) {
      var id = event.target.id.substr(7, 1);
      addOne(id);
    });
  });
});
// display the next row and hide the last 'Add one' button
function addOne(id) {
  $('addone_'+id).setStyle('display', 'none');
  $('recipient_'+id).setStyle('display', 'block');
};

Note that in this code substr(7, 1); is used to get the number from the end of the Add One button id. That is addone_3 gives 3. If the maximum is more than 9 then some adjustment will be needed for example

var id = event.target.id.replace('addone_', '');
The resulting data is returned as a sub array in $form->data['recipient'] and may need further processing before it can be saved or used in an email. Here's an example form the debugger output on the demo form:
[recipient] => Array (
  [1] => Array (
    [name] => Simon
    [address] => 12 High Steet
  )
  [2] => Array (
    [name] => Steven
    [address] => 72 Main Street
  )
  [3] => Array (
    [name] => Sue
    [address] => 4 Back Street
  )
  [4] => Array (
    [name] => Sally
    [address] => 99 ave de l'Opera
  )
  [5] => Array (
    [name] => Sherlock
    [address] => 1278 6th Steet
  )
)
 

2Checkout.com

2CheckOut.com Inc. (Ohio, USA) is an authorized retailer for goods and services provided by ChronoEngine.com