0

I've used Repeatable fields in component Options in the past, and am now trying to use that field type in a Form within my component, but the values are not being saved.

Using Firebug, I can see that the data I entered into the modal form is being retained, and (what appears to be) an array of JSON objects is being posted. That data does get posted (as I can see with Tamper), but this seems to be where thing go awry.

Only the left brace appears to be available from $_POST when I check from the first line of index.php, or using the native $data variable within the model.

With Joomla 3.6, how do I properly post the data from the Repeatable field in my model so that it is saved properly in it's entirety to the database in the same way the component Options do from config.xml?

The Form XML

<field name="chapters" type="repeatable" icon="list" label="Agenda Index" description="Start/Stop times of Agenda items for the meeting Video" >
    <fieldset hidden="true" name="chapters_modal" repeat="true">
        <field name="chapter_start" label="Start Time"  size="15" type="text" />
        <field name="chapter_end"   label="Stop Time"   size="15" type="text" />
        <field name="chapter_name"  label="Name"        size="50" type="text" />
    </fieldset>
</field>

POST data (via Tamper, before POSTing to Joomla)

Content-Disposition: form-data; name="jform[chapters]"
{
    "chapter_start" : ["01:01:01","03:03:03"]   ,
    "chapter_end"   : ["02:02:02","04:04:04"]   ,
    "chapter_name"  : ["chapter1","Chapter 2"]
}

Model $data (Note only the left brace in the chapters element)

public function save($data){
Array
(
    [id] => 9
    [chapters] => {             
    [video_mp4] => 20150226_regular.9.mp4
    [audio_mp3] => 20150226_regular.9.mp3
)

Model Save

$table = $this->getTable();
if ($table->save($data) === true)....

Database column result (where the dots are actually blanks)

{..............   

Form HTML

<form
    id="form-video" 
    action="/index.php?option=com_example&amp;task=video.save&amp;Itemid=185" 
    method="post" 
    class="form-validate form-horizontal" 
    enctype="multipart/form-data"
>

<div class="controls">
    <button class="open-modal btn" id="jform_chapters_button"><span class="icon-list"></span> Select</button>
    <input 
        name="jform[chapters]" id="jform_chapters" 
        value="{
            "chapter_start":["01:01:00","02:02:02"],
            "chapter_end":["01:01:59","02:02:59"],
            "chapter_name":["Chapter 1","Chapter 2"]
            }" 
        class="form-field-repeatable" 
        data-container="#jform_chapters_container" 
        data-modal-element="#jform_chapters_modal" 
        data-repeatable-element="table tbody tr" 
        data-bt-add="a.add" data-bt-remove="a.remove" 
        data-bt-modal-open="#jform_chapters_button" 
        data-bt-modal-close="button.close-modal" 
        data-bt-modal-save-data="button.save-modal-data" 
        data-maximum="999" 
        data-input="#jform_chapters" 
        type="hidden"
    >
</div>
1

Please note that the original repeatable field is deprecated in favor of the subform field.

I think you need to deal with the data before saving it to the database. What I did for a single text field within a subform field was this in the postSaveHook method of the controller:

if (!empty($validData['subform']))
{
    $tupel = new stdClass;
    $tupel->id = 0;
    $tupel->refere_id = (int) $validData['id'];

    foreach ($validData['subform'] as $tmp)
    {
        if (empty($tmp['repeatable']))
        {
            continue;
        }

        $tupel->repeatable= $tmp['repeatable'];

        $db->insertObject('#__cross_table_for_repeatable', $tupel);
    }
}

subform is the name of the subform field, repeatable the name of the actual repeated field containing the value.

In my case, I did store it into a n:n table. In your case you may store it as JSON string into the regular table. In that case you would have to convert it from an array to a JSON string before the saving happens. You should be able to do that in the models validate method.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.