ModelAdmin - SS4.4 custom filters no long work from documentation

Silverstripe Version:
4.4

Question:
Currently with SS4.3 and above Model Admins getSearchContext ModelAdmin – SilverStripe Documentation is deprecated as ss 4.3 + is using GridFieldFilterHeader instead. WIth this you have to add a custom extension targeting your model admin and have a custom updateSearchContext function - ex.

    class FormRequestAdminExtension extends DataExtension{
        public function updateSearchContext($context)
        {

            $context->getFields()->push(DateField::create('q[Start]','Start'));
            $context->getFields()->push(DateField::create('q[End]','End'));

            return $context;
        }
    }

This works great in adding the form fields but when I am in my model admin and in the getList() function, I can’t seem to access these new search params to filter.

You used to do something like the following -

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

    $params = $this->getRequest()->requestVar('q'); // use this to access search parameters

This no longer seems to work as when I look at the params they are always empty. If I get all requestVars I can see there is the gridfield state but I am not able to access what the filters are.

Does anyone know how to properly setup custom filters with ModelAdmin for ss4.3+?

This was broken in 4.3 and hasn’t been fixed as far as I know, but there is a workaround. See function getSearchContext in extension of modeladmin is not called anymore · Issue #8827 · silverstripe/silverstripe-framework · GitHub

Thanks, looks like I found that solution (sort of) in my testing. Will see if that getFilterParams will work with the export button too.

Yep after testing utilizing the solution with the getFilterParams() on the bug -

    public function getFilterParams()
    {
        $class = $this->sanitiseClassName($this->modelClass);
        $body  = $this->getRequest()->getBody();

        parse_str($body, $array);

        $params = [];

        // first, try to get params from filter state in request body
        if (isset($array['filter'][$class]) && is_array($array['filter'][$class])) {
            $params = $array['filter'][$class];
        }

        // second, try to get params from GridFieldFilterHeader state in request body
        if (empty($params) && isset($array[$class]['GridState']) && $array[$class]['GridState']) {
            $gridState = json_decode($array[$class]['GridState'], true);

            if (isset($gridState['GridFieldFilterHeader']['Columns'])
                && is_array($gridState['GridFieldFilterHeader']['Columns'])) {
                $params = $gridState['GridFieldFilterHeader']['Columns'];
            }
        }

        // third, try to get params from GridFieldFilterHeader state in request vars
        if (empty($params) && $requestVar = $this->getRequest()->requestVar($class)) {
            if (isset($requestVar['GridState']) && !empty($requestVar['GridState'])) {
                $gridState = json_decode($requestVar['GridState'], true);

                if (isset($gridState['GridFieldFilterHeader']['Columns'])
                    && is_array($gridState['GridFieldFilterHeader']['Columns'])) {
                    $params = $gridState['GridFieldFilterHeader']['Columns'];
                }
            }
        }

        return $params;
    }

And using this in your getList() function will allow for the gridfield to filter properly, as well as allow the export button to include the filtered context.

Example get list -

    public function getList()
    {
        $list = parent::getList();
        $params = $this->getFilterParams();


        if(isset($params['Created:GreaterThanOrEqual'])){
            $list = $list->filter(['Created:GreaterThanOrEqual' => $params['Created:GreaterThanOrEqual']]);
        }
        if(isset($params['Created:LessThanOrEqual'])){
            $list = $list->filter(['Created:LessThanOrEqual' => $params['Created:LessThanOrEqual']]);
        }

        return $list;
    }

So I was able to try some other things - Essentially I have the following now -

DataExtension for model admin class- update search context

    class FormRequestAdminExtension extends DataExtension{
        public function updateSearchContext($context)
        {

            $context->getFields()->push(DateField::create('Created:GreaterThanOrEqual','Start'));
            $context->getFields()->push(DateField::create('Created:LessThanOrEqual','End'));

            return $context;
        }
    }

Model Admin getList

    public function getList()
    {
        $list = parent::getList();
        $params = $this->getRequest()->requestVar('filter');
        $filters = $params[$this->sanitiseClassName($this->modelClass)];

        if($filters){
            return $list->filter($filters);
        }

        return $list;
    }

This filters the data fine now as I would like. The only thing is the export button now doesn’t respect this search context. Anyone know how to get an export of just your search results in model admin?

Any hints as to why the SilverWare Select2 field type wouldn’t send filters when using the custom approaches outlined here?

A DropdownField instance does work.

Asking here as it’s likely specific to this custom setup.