CakePHP: add fields to form (dynamically)

cakephpforms

I am trying to dynamically add fields to my CakePHP form, but it seems that each method I used had its own downsides which I couldn't fix. Here is what I tried:

  1. Don't add a new input, just separate the values in a single input with a comma. It seemed pretty easy, with some problems when trying to explode the input and save each value in a new row in the database. But I abandoned the idea when I had to edit these values…gather all the values and implode them in an input, then when I saved check whether all values are still there, if not, delete the corresponding row from the table…To much work to do.

  2. I tried creating new inputs on the fly, with JS. But here, I stumbled upon 2 problems: the Security component, which was throwing a blackhole attempt (and I really need this component to check the integrity of the form) and the fact that if validation fails, my inputs will disappear together with their values. I must add that a single Model may have unlimited fields, so the inputs will be something like name=[Model][14][field], name=[Model][17][field], therefore I can't restrict the Security component not to validate those certain inputs (I know their IDs only when I add them with JS, anyway, way after the Security component builds its data).

  3. Adding fields with PHP (therefore, reload the page after a new field is added), but I cannot seem to find out how do I add a field exactly after another present field, and also, how to maintain the input's data upon validation errors.

Any suggestion is highly appreciated!

Thank you!

Best Answer

I'm not sure I can give you a full answer to your question, but hopefully I can give you a couple ideas.

I found myself in a similar situation when trying to create an admin system for polls.

Each Poll had many PollOptions and I wanted to make it possible to dynamically add as many poll options as needed on my polls/admin_edit page.

I managed this with CakePHP's built-in functionality plus a bit of Javascript.

When building the form in the admin_edit view, I first put in the Poll fields and under that I added this:

<div id="poll-options">
<?php 
if (isset($this->data['PollOption'])) {
    $i = 0;
    foreach ($this->data['PollOption'] as $opt) {
        echo $form->hidden("PollOption.$i.id");
        echo $form->input("PollOption.$i.name", array('label' => "Option " . ($i + 1)));
        $i++;
    }
}
?>
</div>

$this->data was set in PollsController. If the Poll already had related PollOptions, they were also included in $this->data. Also, if the form had already been submitted and there were validation errors, all the needed PollOption fields were built again when the page displayed because they were still in $this->data from the controller.

So that took care of making sure I always had the fields I needed in the view.

When the form was submitted, I attempted to save the data with a simple

$this->Poll->saveAll($this->data, array('atomic' => false, 'validate' => 'first'));

(You can check the CakePHP API or docs if you're not sure of the above syntax)

I used Javascript (jQuery) to dynamically add the PollOption fields:

$('#add-option-button').click(function(event){
    var optionCount = $('#poll-options > div').size() + 1;
    var inputHtml = '<div class="input text"><label for="PollOption' + optionCount + 'Name">Option ' + optionCount
        + '</label><input id="PollOption' + optionCount + 'Name" type="text" name="data[PollOption][' + optionCount + '][name]" /></div>';
    event.preventDefault();
    $('#poll-options').append(inputHtml);
});

You mentioned you were doing this yourself, but you shouldn't have any trouble with it if you don't try to use the Security component on the form.

Hope this helps point you in the right direction, or maybe give you some ideas.