Scaffolding Forms With many_many Relations (And Checkboxes)

In one of my latest projects we have a lot of frontend forms related to DataObjects. Instead of building the FieldList manually we use the form scaffolder, a great tool. But with great tools comes great confusion when it doesn't work as expected out of the box.

When using the scaffolder is easy like calling $this->scaffoldFormFields(). When calling it you can pass a configuration array to it. Default configuration is:

array(
    'tabbed' => false,
    'includeRelations' => false,
    'restrictFields' => false,
    'fieldClasses' => false,
    'ajaxSafe' => false
)

restrictFields is useful when you only want a small subset of $db-Fields scaffolded. When you don't restrict the fields, every database field added will be scaffolded automatically. You might appreciate it - or not. With includeRelations set to true also $has_one, $has_many etc. are generated.

By default the scaffolder asks the db-field to generate the FormField. You can overwrite this and tell the scaffolder to use a special FormField by defining fieldClasses.

Here is a working example for generating a CheckboxSetField for a many_many relation:

<?php

class Job extends DataObject
{
    private static $db = [
        'SomeField' => 'Varchar',
        'StartDate' => 'Date',
        'Comment' => 'Text'
    ];


    private static $many_many = [
        'JobCountries' => 'Country',
    ];

    /**
     * Is called from the Form
     *
     * @return FieldList
     */
    public function getFrontendFields(){
        $fields = $this->scaffoldFormFields([
            'includeRelations' => true,
            'fieldClasses' => [
                'JobCountries' => 'CheckboxSetField',

            ]
        ]);

        $fields->dataFieldByName('JobCountries')
            ->setSource(Country::get()->map())
            ->setValue(null, $this);

        //change fieldOrder
        $fieldOrder = [
            'StartDate',
            'SomeField',
            'JobCountries',
            'Comment'
        ];

        $fields->changeFieldOrder($fieldOrder);

        return $fields;
    }
}

After scaffoling the the FieldList we had to modify the CheckboxSetField and add the source (a DataList with all Countries available) and set the current value (the actual record). CheckboxSetField grabs the according ManyManyRelationList and sets all current items as "checked":

screenshot scaffolding many many

After all we tell the FieldList to reorder the fields by calling changedFieldOrder() which works great as long as we don't have nested fields, e.g. Tabs or FieldGroups.

Rate this post (1 ratings)

Post your comment

Comments

No one has commented on this page yet.

RSS feed for comments on this page | RSS feed for all comments