Filtered ModelAdmin views and redirects for missing records

Sometimes you want to have multiple views of the same DataObject in the same ModelAdmin, just using different tabs. GridField allows you to filter based on the currently active model (determined via the new modelTab alias, rather than the full class name).

This can cause usability issues as users bookmark or share item URLs, but those items stop matching the filter for a specific tab. For example, an item moving from “active” to “inactive”. You can fix this by using the new GridField->setRedirectMissingRecords() functionality, and defining a (conditional) CMSEditLink() method on your DataObject.

<?php

namespace MyNamespace\Models;

use SilverStripe\ORM\DataObject;
use MyNamespace\Admin\MyAdmin;

class MyItem extends DataObject
{

    private static $db = [
        'IsActive' => 'Boolean',
     ];

    public function CMSEditLink()
    {
       $slug = $this->IsActive ? 'active' : 'inactive';
       return Director::baseUrl() . implode('/', [
            'admin',
             Config::inst()->get(MyAdmin::class, 'url_segment'),
             $slug,
             'EditForm/field',
             $slug,
             'item',
             $object->ID
        ]);
    }

}
<?php

namespace MyNamespace\Admin;

use SilverStripe\Admin\ModelAdmin;
use MyNamespace\Models\MyItem;
use SilverStripe\Forms\GridField\GridFieldDetailForm;

class MyAdmin extends ModelAdmin {

    private static $managed_models = [
        'active' => ['title' => 'Active', 'dataClass' => MyItem::class],
        'inactive' => ['title' => 'Inactive', 'dataClass' => MyItem::class],
    ];

    private static $menu_title = 'MyItems';

    private static $url_segment = 'items';

    public function getList()
    {
        $list = parent::getList();

        return $list->filter([
            'IsActive' => $this->modelTab == 'active',
        ]);
    }

    public function getEditForm($id = null, $fields = null)
    {
        $form = parent::getEditForm($id, $fields);

        /** @var GridField $grid */
        $grid = $form->Fields()->dataFieldByName($this->modelTab);
        /** @var GridFieldConfig $config */
        $config = $grid->getConfig();

        // Customise external link formatting
        if ($this->modelClass == MyItem::class) {
            // Allow redirection to risks in other sections
            /** @var GridFieldDetailForm */
            $component = $config->getComponentByType(GridFieldDetailForm::class);
            $component->setRedirectMissingRecords(true);
        }

        return $form;
    }

}
1 Like

Posted this a bit too early, right now it still requires this PR: NEW: Add GridFieldDetailForm::setRedirectMissingRecords() by sminnee · Pull Request #9655 · silverstripe/silverstripe-framework · GitHub