silverstripe-terraformers/gridfield-rich-filter-header

来自 GridField 的丰富筛选头组件

3.0.0 2023-12-22 00:17 UTC

README

Latest Stable Version Total Downloads Latest Unstable Version License PHP Version Require

GridField 组件旨在替换默认的 GridFieldFilterHeader 组件,并提供原始版本中不可用的丰富功能。

以下是这些组件的简要比较

GridFieldFilterHeader(原始组件)

  • 没有可用的筛选相关配置
  • 只有当 GridField 列名称与 DB 列名称匹配时,筛选功能才有效,这在许多情况下并不适用(日期格式、列内容获取函数)
  • 始终使用 TextField 作为筛选输入 FormField
  • 始终使用 PartialMatchFilter 进行筛选
  • 始终将对应 GridField 列的数据库字段应用筛选
  • 无法选择不显示筛选

RichFilterHeader(本模块中的组件)

  • 筛选可以完全配置
  • 您可以为 GridField 列名称与 DB 列名称之间的映射指定,这样您就可以自由地使用日期格式、列内容获取函数等特性
  • 您可以选择在筛选中使用任何 FormFieldTextField 仅作为默认选项使用
  • 支持使用 XHR 的 FormFields,例如 AutoCompleteField
  • 可以使用任何 SearchFilter,默认情况下使用 PartialMatchFilter
  • 您可以通过指定自己的筛选方法来根据任何数据进行筛选

总的来说,此模块允许您完全自定义 GridField 筛选,包括罕见边缘情况和特殊要求。

需求

  • 表头组件需要存在于 GridField 中(例如 GridFieldSortableHeader
  • 表的最后一列需要有一个空白的表头单元格,以便在那里显示筛选小部件
  • 例如,您不能同时在最后一列具有排序表头小部件和筛选小部件

安装

composer require silverstripe-terraformers/gridfield-rich-filter-header

基本配置

完整的筛选配置格式如下所示

'GridField_column_name' => [
    'title' => 'DB_column_name',
    'filter' => 'search_filter_type',
],

具体示例

'Expires.Nice' => [
    'title' => 'Expires',
    'filter' => 'ExactMatchFilter',
],

search_filter_type 可以是任何 SearchFilter,有关更多信息,请参阅搜索筛选文档

https://docs.silverstripe.org/en/4/developer_guides/model/searchfilters/

还有更短的配置格式可用

字段映射版本不包括筛选规范,将使用 PartialMatchFilter。如果您对使用 PartialMatchFilter 满意,应使用此配置

'GridField_column_name' => 'DB_column_name',

白名单版本不包括筛选规范和字段映射。此配置将使用 PartialMatchFilter 并假定 GridField_column_nameDB_column_name 相同

'GridField_column_name',

多个筛选配置示例

$gridFieldConfig->removeComponentsByType(
    GridFieldSortableHeader::class,
    GridFieldFilterHeader::class,
);

$sort = new RichSortableHeader();
$filter = new RichFilterHeader();
$filter
    ->setFilterConfig([
        'getFancyTitle' => 'Title',
        'Expires.Nice' => [
            'title' => 'Expires',
            'filter' => 'ExactMatchFilter',
        ],
    ]);


$gridFieldConfig->addComponent($sort, GridFieldPaginator::class);
$gridFieldConfig->addComponent($filter, GridFieldPaginator::class);

如果未通过 setFilterConfig 方法提供配置,筛选配置将回退到 GridField 中列出的 DataObjectsearchable_fields。如果 searchable_fields 配置不可用,则使用 summary_fields 代替。

请确保在 GridFieldPaginator 之前添加 RichFilterHeader 组件,否则您的分页将会损坏,因为您始终希望在分页之前进行筛选。排序头组件也需要替换,以允许显示筛选展开按钮。

字段配置

任何 FormField 都可用于过滤。只需将其添加到过滤配置,如下所示

->setFilterFields([
    'Expires' => DateField::create('', ''),
])

字段的 名称 可以留空,因为它会自动填充。我建议将 标题 也留空,因为你可能不需要显示它,因为在大多数情况下它与 GridField 列表头标题重复。

过滤方法

此配置涵盖了大多数边缘情况和特殊要求,在这些情况下标准 SearchFilter 不够用。如果为字段指定了过滤方法,它将覆盖标准过滤。过滤方法是一个回调,它将被应用于 DataList,你可以在回调内部添加任何所需的功能。确保你的回调返回一个与原始相同的 DataClassDataList

->setFilterMethods([
    'Title' => function (DataList $list, $name, $value) {
        // my custom filter logic is implemented here
        return $filteredList;
    },
])

请注意,$name 将具有配置中的 DB_column_name 的值。

为了您的方便,提供了一些过滤方法来覆盖某些情况。

  • AllKeywordsFilter - 将文本输入按空格分割成关键词,并搜索包含所有关键词的记录
  • ManyManyRelationFilter - 将搜索与特定记录通过 many_many 关系关联的记录

这两个过滤器都可以在 setFilterMethods 中使用,如下所示

->setFilterMethods([
    'Title' => RichFilterHeader::FILTER_ALL_KEYWORDS,
])

其他示例

示例 #1

  • 使用 AutoCompleteField 进行过滤,并通过 AllKeywordsFilter 过滤方法进行过滤
  • 使用 DateField 进行过滤,并通过 StartsWithFilter 进行过滤
$gridFieldConfig->removeComponentsByType(
    GridFieldSortableHeader::class,
    GridFieldFilterHeader::class,
);

$sort = new RichSortableHeader();
$filter = new RichFilterHeader();
$filter
    ->setFilterConfig([
        'Label',
        'DisplayDateEnd.Nice' => [
            'title' => 'DisplayDateEnd',
            'filter' => 'StartsWithFilter',
        ],
    ])
    ->setFilterFields([
        'Label' => $dealsLookup = AutoCompleteField::create('', ''),
        'DisplayDateEnd' => DateField::create('', ''),
    ])
    ->setFilterMethods([
        'Label' => RichFilterHeader::FILTER_ALL_KEYWORDS,
    ]);
    
$dealsLookup
    ->setSourceClass(SystemDeal::class)
    ->setSourceFields(['Label'])
    ->setDisplayField('Label')
    ->setLabelField('Label')
    ->setStoredField('Label')
    ->setSourceSort('Label ASC')
    ->setRequireSelection(false);
    
$gridFieldConfig->addComponent($sort, GridFieldPaginator::class);
$gridFieldConfig->addComponent($filter, GridFieldPaginator::class);

AutoCompleteField DateField

示例 #2

  • 使用 DropdownField 进行过滤,并通过 ManyManyRelationFilter 进行过滤

请注意,在 GridField 中列出的条目与 TaxonomyTerm 有一个名为 TaxonomyTermsmany_many 关系

$gridFieldConfig->removeComponentsByType(
    GridFieldSortableHeader::class,
    GridFieldFilterHeader::class,
);

$sort = new RichSortableHeader();
$filter = new RichFilterHeader();
$filter
    ->setFilterConfig([
        'Label' => 'TaxonomyTerms',
    ])
    ->setFilterFields([
        'TaxonomyTerms' => DropdownField::create(
            '',
            '',
            TaxonomyTerm::get()->sort('Name', 'ASC')->map('ID', 'Name')
        ),
    ])
    ->setFilterMethods([
        'TaxonomyTerms' => RichFilterHeader::FILTER_MANY_MANY_RELATION,
    ]);
    
$gridFieldConfig->addComponent($sort, GridFieldPaginator::class);
$gridFieldConfig->addComponent($filter, GridFieldPaginator::class);

DropdownField

示例 #3

  • 使用 TextField(带自定义占位符文本)和自定义过滤方法进行过滤

我们的自定义过滤方法通过 PartialMatch 过滤器根据三个不同的 DB 列表进行过滤。

$gridFieldConfig->removeComponentsByType(
    GridFieldSortableHeader::class,
    GridFieldFilterHeader::class,
);

$sort = new RichSortableHeader();
$filter = new RichFilterHeader();
$filter
    ->setFilterConfig([
        'Label',
    ])
    ->setFilterFields([
        'Label' => $label = TextField::create('', ''),
    ])
    ->setFilterMethods([
        'Label' => function (DataList $list, $name, $value) {
            return $list->filterAny([
                'Label:PartialMatch' => $value,
                'TitleLineOne:PartialMatch' => $value,
                'TitleLineTwo:PartialMatch' => $value,
            ]);
        },
    ]);

$label->setAttribute('placeholder', 'Filter by three different columns');
$gridFieldConfig->addComponent($sort, GridFieldPaginator::class);
$gridFieldConfig->addComponent($filter, GridFieldPaginator::class);

示例 #4

  • 使用 DropdownField 设置 has_one 关系的完整代码示例

此示例涵盖了

  • Player(有一个 Team
  • Team(有多个 Player
  • PlayersAdmin
<?php

namespace App\Models;

use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\HasManyList;

/**
 * @property string $Title
 * @method HasManyList|Player[] Players()
 */
class Team extends DataObject
{
    /**
     * @var string
     */
    private static $table_name = 'Team';

    /**
     * @var array
     */
    private static $db = [
        'Title' => 'Varchar',
    ];

    /**
     * @var array
     */
    private static $has_many = [
        'Players' => Player::class,
    ];
}
<?php

namespace App\Models;

use SilverStripe\ORM\DataObject;

/**
 * @property string $Title
 * @property int $TeamID
 * @method Team Team()
 */
class Player extends DataObject
{
    /**
     * @var string
     */
    private static $table_name = 'Player';

    /**
     * @var array
     */
    private static $db = [
        'Title' => 'Varchar',
    ];

    /**
     * @var array
     */
    private static $has_one = [
        'Team' => Team::class,
    ];

    /**
     * @var array
     */
    private static $summary_fields = [
        'Title',
        'Team.Title' => 'Team',
    ];
}
<?php

namespace App\Admin;

use App\Models\Player;
use App\Models\Team;
use SilverStripe\Admin\ModelAdmin;
use SilverStripe\Forms\DropdownField;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\Form;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\GridField\GridFieldFilterHeader;
use SilverStripe\Forms\GridField\GridFieldPaginator;
use Terraformers\RichFilterHeader\Form\GridField\RichFilterHeader;

class PlayersAdmin extends ModelAdmin
{
    /**
     * @var array
     */
    private static $managed_models = [
        Player::class => ['title' => 'Players'],
    ];

    /**
     * @var string
     */
    private static $menu_title = 'Players';

    /**
     * @var string
     */
    private static $url_segment = 'players';

    /**
     * @param mixed|null $id
     * @param FieldList|null $fields
     * @return Form
     */
    public function getEditForm($id = null, $fields = null): Form
    {
        $form = parent::getEditForm($id, $fields);

        /** @var GridField $gridField */
        $gridField = $form->Fields()->fieldByName('App-Models-Player');

        if ($gridField) {
            // Default sort order
            $config = $gridField->getConfig();

            // custom filters
            $config->removeComponentsByType(
                GridFieldSortableHeader::class,
                GridFieldFilterHeader::class,
            );
            
            $sort = new RichSortableHeader();
            $filter = new RichFilterHeader();
            $filter
                ->setFilterConfig([
                    'Title',
                    'Team.Title' => [
                        'title' => 'TeamID',
                        'filter' => 'ExactMatchFilter',
                    ],
                ])
                ->setFilterFields([
                    'TeamID' => $team = DropdownField::create(
                        '',
                        '',
                        Team::get()->sort('Title', 'ASC')->map('ID', 'Title')
                    ),
                ]);


            $team->setEmptyString('-- select --');
            $config->addComponent($sort, GridFieldPaginator::class);
            $config->addComponent($filter, GridFieldPaginator::class);
        }

        return $form;
    }
}

现在我们可以通过球队过滤球员。

DropdownField