SS4: edit many_many_extraFields in a GridField detail form

In a recent project I had a $many_many relation between TeamMember and TeamGroup where each member can have a different role per group. I solved this with a manymany relation and extraFields, but how can I tell my GridField to show me a nice form field for editing the "TeamRole" extra field?

My code (with namespaces stripped) is like:

class TeamMember extends DataObject
{
[..]

    private static $many_many = [
        'TeamGroups' => TeamGroupPage::class,
    ];

    private static $many_many_extraFields = [
        'TeamGroups' => [
            'TeamRole' => 'Varchar',
            'SortOrder' => 'Int'
        ]
    ];
}

and the counterpart

class TeamGroupPage extends Page
{
[..]

    private static $belongs_many_many = [
        'TeamMembers' => TeamGroup::class,
    ];


}

When I'm on the TeamGroupPage and try to add or edit a TeamMember we need to modify the GridFieldDetailForm to to add the extra fields:

//on class TeamGroupPage

public function getCMSFields()
    {
        $fields = parent::getCMSFields();
        $conf = GridFieldConfig_RelationEditor::create(20);

        $teamGrid = Gridfield::create(
            'TeamMembers',
            'Team Members',
            $this->TeamMembers(),
            $conf
        );

        $detailFormComponent = $teamGrid->getConfig()->getComponentByType(GridFieldDetailForm::class);
        $detailFormComponent->setItemEditFormCallback(function ($form, $itemrequest) {
            $record = $itemrequest->record;
            $roleField = TextField::create('ManyMany[TeamRole]', 'Team Role', $record->TeamRole);
            $form->Fields()->add($roleField);
        });

        $fields->addFieldToTab('Root.TeamMembers', $teamGrid);

        return $fields;
    }

We get the GridFieldDetailForm component of the grid field's config and modify it by adding a field to TeamMember's CMSFields. With the method setItemEditFormCallback() we can add an anonymous function to add the needed field(s). Manymany extraFields are saved using the ManyMany[FieldName] syntax, so we need ManyMany[TeamRole] as the FieldName; we also need to grab the current value from $itemrequest->record.

Now John Doe can be "Boss" of the A-Team and normal member of team B...

Rate this post

Post your comment

Comments

  • Holger 28/05/2020 12:32pm (4 years ago)

    Hi Gregor,

    when saving the form, the value from ManyMany[TeamRole] is saved, but the form returns the old value.
    If you reload the form you see, that it was saved correctly but the value was not reloaded.

    My gridfield is not nested in page but in another dataObject.

    Any idea how to solve that?

    Kind regards
    Holger

  • Paweł P. 17/01/2020 6:07pm (4 years ago)

    Hello, works nice – but after save, input show old data, data in DB was changed so after refresh new value appears...

  • Eric Hes 18/10/2018 4:43pm (5 years ago)

    Thanks Werner, this was exactly what I needed, saved a lot of time with this clear example :)

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