Multiple File Uploads CakePHP jQuery

Creating a basic form where you can add file inputs for file uploads dynamically using jQuery for the client side and cakePHP for the server side.

First create the form with your form fields in it:

<?php
echo $form->create('NewsItem', array('type' => 'file'));
 
        //Form for adding the plugin files
        echo $form->input('PluginFile.1.description');
        echo $form->input('PluginFile.1.File', array('label'=>'File', 'type'=>'file'));
        echo $form->button('Add File', array('id' => 'addPluginFile'));
 
 echo $form->end('Submit');
?>
<div id="PluginFiles"></div>

I'm using a couple of fields for a plugin file object in this instance.

 

 $(document).ready(function(){
    //onClick event for plugin file add button:
    $('#addPluginFile').click(addPluginFileInputs);
 });

Adding an event handler for the 'Add File' button using jQuery. Then the handler for the button which clones all the fields for the plugin file, renames them with increasing ids so that cakePHP can handle them as an array nicely...

 var pluginFileInputCounter = 1;
 var addPluginFileInputs = function(event) {

     //Get plugin file inputs, clone them
     $("input[name*='[PluginFile][1]']").clone().each(function() {

        //Rename the fields increasing numbers:
        this.name = this.name.replace(/\[(\d+)\]/, function (m,x) {
            return '[' + (parseInt(x) + pluginFileInputCounter) + ']'
        });

        //Clear the values of the cloned fields:
        this.value = '';

        //Append them to the form:
        $('#PluginFiles').append($(this));
     });
     pluginFileInputCounter++;
 }

Now overwriting the save() or saveAll() function in the object which in my case is PluginFile to save the file and create it on the server:

//Save the plugin file details
if (!parent::save($data, $validate, $fieldList)) {
   return false;
}
//Move the plugin file
if (!move_uploaded_file($data['PluginFile']['File']['tmp_name'], UPLOADS . $data['PluginFile']['filename'])) {
    return false;
}

Cheers to the guy on the #javascript channel who showed me how to use a function in .replace() like that. The only problems I had with this was overwriting both the save() and saveall() functions as saveall() invokes save() actually.