Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Allow each DataObject subclass to define its own formfield when autoscaffolded from relation #11079

Closed
GuySartorelli opened this issue Nov 29, 2023 · 3 comments

Comments

@GuySartorelli
Copy link
Member

GuySartorelli commented Nov 29, 2023

Currently, we have the following hard-coded logic for autoscaffolding relations:

  • has_one relations are autoscaffolded as one of:
    • DropdownField if there's less than a configurable threshold
    • NumericField if there's more than a configurable threshold
    • FileHandleField (usually UploadField) if it's a file or image
  • has_many and many_many relations are autoscaffolded as GridField fields inside a tab.

Some models have specific form fields they should be used with. For example, a Link model might have a specific LinkField for has_one and MultiLinkField for has_many relations.
Currently, adding the form fields for these models often requires first removing the original autoscaffolded field. It would be way better if it just autoscaffolded the correct field from the start.

We should allow each model to instantiate its own form field when being autoscaffolded from a relation.

Acceptance criteria

  • The current default logic still applies (i.e. no breaking changes)
    • File is updated to auto-scaffold UploadField for has_one relations
    • Other DataObjects are retain the current auto-scaffold logic that generates a DropdownField.
  • Any model can pre-define its own autoscaffolded form field for has_one relations.
  • Any model can pre-define its own autoscaffolded form field for has_many relations.
  • Any model can pre-define its own autoscaffolded form field for many_many relations.

PRs

@mooror
Copy link
Contributor

mooror commented Nov 30, 2023

This would be a marvelous addition to the DataObject infrastructure 💯

@maxime-rainville
Copy link
Contributor

DBField can scaffold form field to manage what should be used to managed them. e.g.

public function scaffoldFormField($title = null, $params = null)
{
return MoneyField::create($this->getName(), $title)
->setLocale($this->getLocale());
}

HasOne relation use the DBForeignKey to scaffold their field which builds a SearchableDropdownField for most DataObject. It also has a bit of hard coded logic for File.

public function scaffoldFormField($title = null, $params = null)
{
if (empty($this->object)) {
return null;
}
$relationName = substr($this->name ?? '', 0, -2);
$hasOneClass = DataObject::getSchema()->hasOneComponent(get_class($this->object), $relationName);
if (empty($hasOneClass)) {
return null;
}
$hasOneSingleton = singleton($hasOneClass);
if ($hasOneSingleton instanceof File) {
$field = Injector::inst()->create(FileHandleField::class, $relationName, $title);
if ($hasOneSingleton instanceof Image) {
$field->setAllowedFileCategories('image/supported');
}
if ($field->hasMethod('setAllowedMaxFileNumber')) {
$field->setAllowedMaxFileNumber(1);
}
return $field;
}
$labelField = $hasOneSingleton->hasField('Title') ? 'Title' : 'Name';
$list = DataList::create($hasOneClass);
$threshold = self::config()->get('dropdown_field_threshold');
$overThreshold = $list->count() > $threshold;
$field = SearchableDropdownField::create($this->name, $title, $list, $labelField)
->setIsLazyLoaded($overThreshold)
->setLazyLoadLimit($threshold);
return $field;
}

They are many scenarios where SearchableDropdownField is not the best form field to use for a specific DataObject. e.g.: Link, SiteTree, Taxanomie Tags.

I'm thinking it would be trivial to update DBForeignKey::scaffoldFormField() to call a matching scaffoldFormField on singleton to retrieve its form field:

  • DataObject::scaffoldFormField() could SearchableDropdownField as a sensible default.
  • File could override that default to return an UploadField which would avoid tying DBForeignKey to the File class.
  • Specialised DataObjects like Link can specify their own custom field.

Related issues

@emteknetnz
Copy link
Member

Linked PRs have been merged

# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
None yet
Development

No branches or pull requests

4 participants