Silverstripe-framework: ModelAdmin SearchForm filters only on the first field

Created on 17 Dec 2019  路  10Comments  路  Source: silverstripe/silverstripe-framework

Affected Version

4.4.4

Description

So I have this model admin instance displaying members

If I type something in the search bar, it searches only on the first name. Data posted is something like

filter[SilverStripe-Security-Member][FirstName]: ***MYSEARCHQUERYHERE***

it's not searching on all searchable fields by default. which means you need to use the little dropdown to search each time by a specific field. It's very counterintuitive in a google era where people type stuff and expect the system to match records based on that.

Steps to Reproduce

  • Have a model admin managing users
  • Type something in the search box other than the firstname (the Surname for example)
  • Expect a match, but get an empty list

Am I missing something ? Also, it's very confusing at the moment to know how to properly deal with this since we are in the middle of deprecated features (searchform getting replaced by the gridfieldfilterheader).

Any idea how to "simply" match on all searchable columns by default?

affectv4 changminor efformedium impacmedium typUX typenhancement

Most helpful comment

@lerni so since there is no easy solution, I had to build one. not sure it's the best way, but it works!

the class is here
https://github.com/lekoala/silverstripe-base/blob/master/src/ORM/Search/WildcardSearchContext.php

the idea is to override the default search context in the GridFieldFilterHeader

it's not so easy to do, because there is no way to set the searchContext, so I had to use reflection to do so. then, the idea is simply if there is only one search argument to do a filterAny for all availables filters. as an added bonus, i deal with multiple words as multiple AND/OR groups.

sample usage in model admin

        $filter =  $config->getComponentByType(GridFieldFilterHeader::class);
        $wildCardHeader = WildcardSearchContext::fromContext($filter->getSearchContext($gridfield));
        $wildCardHeader->setWildcardFilters(['FirstName', 'Surname','Email']);
        $wildCardHeader->replaceInFilterHeader($filter);

All 10 comments

Same issue bugged me as well. I agree it feels unexpected and counter intuitive.

Hey @lekoala, thanks for raising this! My initial impression is that this would require an expansion of the $searchable_fields config structure to allow applying multiple DataObject fields to a single search field. We likely wouldn't want to make the main search UI match on every field by default, as some fields might not be useful in a search (especially on more complex projects). Definitely worth exploring options, though - I agree that the current behaviour feels unnecessarily shallow.

@Cheddam something like this would work for me

  private static $searchable_fields = [
       'FirstName' => [
          'field' => TextField::class,
          'filter' => 'PartialMatchFilter',
          'global' => true,
       ],
       'Surname' => [
          'field' => TextField::class,
          'filter' => 'PartialMatchFilter',
          'global' => true,
       ],
   ];

this way, you can opt in to filter on multiple fields by default by setting the "global" config to true

Related: #9341 aims to implement proper APIs for determining which (single) field to use for the search bar. When tackling this issue, we'd likely now be looking at expanding that API.

@Cheddam while this is being improved, any idea how to simply allow searching on multiple fields? It's really not clear how to do this properly

@lekoala You might be able to sufficiently modify the behaviour of the default search field by customising getList() on your ModelAdmin - see the ModelAdmin docs for some idea on how custom fields / filtering can be accomplished. This might become a bit easier once #9341 is merged.

@Cheddam i may be wrong, be as far as I can tell, gridfieldfilterheader applies its change AFTER getList is called no? calling something like

public function getList()
{
    $list = parent::getList();
    die($list->sql());

will show a sql statement without any where clause applied (even though I have a search parameter in the search bar)

@lerni so since there is no easy solution, I had to build one. not sure it's the best way, but it works!

the class is here
https://github.com/lekoala/silverstripe-base/blob/master/src/ORM/Search/WildcardSearchContext.php

the idea is to override the default search context in the GridFieldFilterHeader

it's not so easy to do, because there is no way to set the searchContext, so I had to use reflection to do so. then, the idea is simply if there is only one search argument to do a filterAny for all availables filters. as an added bonus, i deal with multiple words as multiple AND/OR groups.

sample usage in model admin

        $filter =  $config->getComponentByType(GridFieldFilterHeader::class);
        $wildCardHeader = WildcardSearchContext::fromContext($filter->getSearchContext($gridfield));
        $wildCardHeader->setWildcardFilters(['FirstName', 'Surname','Email']);
        $wildCardHeader->replaceInFilterHeader($filter);

@Cheddam using my current solution feels much better than the default behaviour. having to click on the dropdown and do a specific search should really not be the default behaviour in my opinion. for members list (and probably lots of other types of data) it makes much more sense to search on firstname, surname and email. i think it's really sad that there is no built in option for this.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

maxime-rainville picture maxime-rainville  路  3Comments

maxime-rainville picture maxime-rainville  路  6Comments

zanderwar picture zanderwar  路  6Comments

leomeloxp picture leomeloxp  路  4Comments

Cheddam picture Cheddam  路  3Comments