Adding form fields via ajax with Mootools

Picture 6I am currently working on a project where the administrator needs to be able to upload any number of items within one master project.

Clearly I didn’t want to present them with a long page of repetative form fields and anyway, there was no way of knowing whether they would need 1, 2 or 20 items.
The solution?
Use some simple mootools ajax magic to fetch the form fields dynamically from an external file.

See Demo

I choose to use ajax rather than coding the form fields directly into the javascript for several reasons.

  1. Firstly because they where a rather complicated mix of all sorts of form fields that would be a nightmare to create through javascript.
  2. Some of the form fields contained data fetched from the database which again would get complicated in amongst “normal” javascript
  3. By using an external file and sending it a defining value, I could use the same code for different forms (using a php switch on the “type” value passed) without having to touch the javascript again.

Here is how I did it:

The HTML

<form method="post" id="item_form" enctype="multipart/form-data">
 <div  id="form_data">
 <!-- the form fields will be loaded here via ajax -->
 </div>
 <div>
 <span id="loading"></span>&nbsp;
 <input type="button" id="add_item" value="Add New Form">
 <input type="submit" value="Submit">
 </div>
 </form>

The JAVASCRIPT (mootools)

window.addEvent('domready', function() {

 var counter=0;
 function new_rows(){
 counter=counter+1;
 var myHTMLRequest = new Request({
 url:'load.ajax.php',
 method:'get',
 autoCancel:true,
 data: {'type':'item','field_name':'add',num:counter},
 onRequest: function() {
 $('loading').set('html','<img src=\"images/ajax-loader.gif\">');
 },
 onComplete: function(responseText) {

 var new_rows = new Element('div', {
 'html': responseText
 });
// inject new fields at bottom
 new_rows.inject($('form_data'),'bottom');

 //    remove loading image
 $('loading').set('text','');
 //    scroll down to new form fields
 var myFx = new Fx.Scroll(window).toElement('table_'+counter);
 }
 }).send();
 }
 $('add_item').addEvent('click', function(e){
 e.stop();  // stop the default submission of the form
 new_rows();
 });

 //load first set of rows - all rows are loaded via ajax
 new_rows();

 });

The PHP (ajax loaded file)

// check we have data
if(!isset($_GET["field_name"])) die("error with data");
if(!isset($_GET["type"]))        die("Error with data");

// define vars (should do more checking here)
$field_name    =    $_GET["field_name"];
$form_type    =    $_GET["type"];
$num        =    $_GET["num"];

switch($form_type){
 case "item":
 echo '
 <table id="table_'.$num.'">
 <tr>
 <td rowspan="4">Table '.$num.'</td>
 <td>Image</td>
 <td><input type="file" name="file_2_upload[]" style="width:99%;"></td>
 </tr>
 <tr>
 <td>Title</td>
 <td><input type="text" name="'.$field_name.'[title][]" value="" style="width:99%;"></td>
 </tr>
 <tr>
 <td>Color</td>
 <td>
 <select name="'.$field_name.'[options]">
 <option value="1">White</option>
 <option value="2">Red</option>
 <option value="3">Blue</option>
 <option value="4">Yellow</option>
 </select>
 </td>
 </tr>
 <tr>
 <td>Description</td>
 <td><textarea name="'.$field_name.'[summary][]" style="width:99%; height:100px;"></textarea></td>
 </tr>
 </table>
 ';
 break;
 default:
 echo "nothing doing, sorry";
 break;
}

Clearly my php file is just an example, you could define and format the form fields however you need for your aplication.

I hope you find it useful 🙂

Post to Twitter

chris@cbolson.com

There are 19 comments in this article:

  1. 15/09/2009Fabio M. Costa says:

    Nice to see you posting about mootools!
    I would add that this is a clear case where you could create a Class! This would leverage the quality of your code, making it easily reusable on other places.

    I would add that you could use some kind of javascript template system to create this kind of thing, without needing to go to the server. But i wont go on further details.

    Nice blog! I signed the RSS.

  2. 15/09/2009Chris says:

    Hi Fabio, thanks for the comments 🙂

    I would make this into a class if I could get my head round how to do it – I fully admit that making classes is not my strong point.
    Feel free to give me some pointers 😉
    I can’t honestly see (due to my ignorance in the matter) how making this into a class would make it anymore flexible though. The only things that should change would be the “type” and “fieldname” values. These could simply set as variables. In my working version they use php variables.

    As regards using a template system, the reason why I choose to load the form fields via ajax was so as to be able to make it easier to programe from a php point of view as some of the fields require
    database data. This way, there is no need to get into complicated javascript structures and, in my opinion, is more flexibe as the ajax file could include whatever is required for each instance.

  3. 18/09/2009New demo for dynamic form fields « Chris Bolson – I digress says:

    […] few days ago I wrote a post to demonstrate how I was adding form fields dynamically with the use of AJAX and […]

  4. 27/01/2010Sirbastian says:

    I was searching for a way to easily do this for the invoicing section of my worktimer.co.uk website and your solution is perfect!

    I have one small issue that is hopefully simple to fix. I’ve got the fields displaying correctly but for some reason they’re not added to to the request vars when the form is submitted.

    Do you know of any way to register the extra elements so they are submitted with the form?

  5. 27/01/2010Chris says:

    @Sirbastian, probably a silly question but, are you sure that you are injecting the dynamic elements within the form tags?
    I used this system on a live site and had no problems.

    Chris

  6. 27/01/2010Sirbastian says:

    Ha I can’t believe daft I was being. I was injecting them into a div just outside the form!

    No surprise that it works perfectly when they’re actually added to the form.

    Cheers for the help and the script!

    Sirbastian

  7. 27/01/2010Chris says:

    🙂 easily done.
    I’m glad that the code is of use to you!

    Your site looks pretty intersting by the way. I have created an account to test it out.

    Chris

  8. 28/01/2010Gerald says:

    Hi, This script is great.
    I want to If it’s posible to adapt this functionality in a Java Server Page.
    Best Regards,

  9. 2/02/2010Chris says:

    Hi, I’m afraid I don’t “do” Java, but feel free to have a go…. 😉

  10. 31/03/2010Dou says:

    Thanks so much for this! I am trying to learn AJAX and your article has helped immensely. I was wondering though why in the data being passed with the request the num:counter were not quoted like ‘type’ and ‘field_name’?

  11. 31/03/2010Chris says:

    The quick and simple answer is because it is numeric and not a string. If you put a number within quotes it becomes a string and that can cause prblems when you need to do mathamatical solutions.

    It is a while since I put that code together, and in fact for the demo and for basic purposes that argument is not needed, to get something like this to work you probably only need to pass the “type”.

  12. 31/03/2010Doug says:

    Thank you for the quick response. I am going to try to adapt this for a set of forms inside of a Joomla environment. What version of Mootools are you using in this example?

    Also, I was curious if it would be possible to pre-fill the questions with user responses stored in a db including the dynamically returned questions? Or asked a different way, do the dynamic fields become a lasting part of the form that can be recalled later?

  13. 31/03/2010Chris says:

    My demo uses Mootools 1.2.3 but there is nothing in there which would prevent it from working in the latest version.

    The fields can be prefilled with database info, infact that was the very reason that I did this in the first place. The code needed to be able to retrieve form data according to options defined by the user.
    Getting the data into to the forms just needs to be done in the php ajax file as per a normal query. They only thing that you might need to alter is to send the “id” of the user to the php file via the ajax call.

  14. 11/07/2010tony says:

    I Want to post form fields with php
    how to get the count of dynamic rows with php ?

  15. 11/07/2010Chris says:

    Hi,
    I don’t qute follow what you want to do.
    You can easily count the fields once the form has been posted with standard php code.
    If you want some sort of counter as the rows are added, you need to do a combination of php and JavaScript (could be done with just JavaScript but you specifically mention php). In fact, if I remember rightly, the javascript code already has a built in counter for making arrays, so maybe you could use that to output it to the page.
    However, as I say, I don’t really understand exactly what it is you want to do so it is hard to give a specific answer.

  16. 9/10/2010Azraf says:

    Nice one. Exactly this one I was searching ….

  17. 15/03/2011Harley says:

    Hmmm – what am I missing here – it’s not printing the form elements

    <?php

    // check we have data
    if(!isset($_GET["field_name"])) die("error with data");
    if(!isset($_GET["type"])) die("Error with data");

    // define vars (should do more checking here)
    $field_name = $_GET["field_name"];
    $form_type = $_GET["type"];
    $num = $_GET["num"];

    switch($form_type){
    case "item":
    echo '

    Table '.$num.'
    Image

    Title

    Color

    White
    Red
    Blue
    Yellow

    Description

    ';
    break;
    default:
    echo "nothing doing, sorry";
    break;
    }

    ?>

  18. 19/03/2011Chris says:

    Hi,
    Could you give a bit more detail regarding your issue?
    The first thing to check is that your are sending the “type” correctly.

    Chris

  19. 22/08/2012Jerry says:

    Chris,

    Awesome script!

    I did find I had to make one adjustment. The counter was adding by 2 on each pass.

    I removed the second ‘counter’. This seems to do the trick.

    I haven’t tested it yet, but I think it’ll work ok.

    Also, short form of ‘counter = counter + 1;’ is ‘counter+=1;’.

    Thanks!

Write a comment: