hesham-fouda/ag-grid-laravel
AG Grid服务器端适配器用于Laravel。
Requires
- php: ^8.1|^8.2
- illuminate/contracts: ^10.0|^11.0
- maatwebsite/excel: ^3.1
- spatie/laravel-package-tools: ^1.14.0
Requires (Dev)
- laravel/pint: ^1.0
- nunomaduro/collision: ^7.8
- nunomaduro/larastan: ^2.0.1
- orchestra/testbench: ^8.8
- pestphp/pest: ^2.0
- pestphp/pest-plugin-arch: ^2.0
- pestphp/pest-plugin-laravel: ^2.0
- phpstan/extension-installer: ^1.1
- phpstan/phpstan-deprecation-rules: ^1.0
- phpstan/phpstan-phpunit: ^1.0
README
此包实现了对AG Grid的服务器端适配器,支持过滤、排序、导出和服务器端选择。
安装
您可以通过composer安装此包
composer require hesham-fouda/ag-grid-laravel
您可以使用以下命令发布配置文件
php artisan vendor:publish --tag="ag-grid-laravel-config"
这是已发布的配置文件的内容
return [ /* * The class that contains the provider for determining the timezone * to use for DateTime formatting in exports. */ 'export_timezone_provider' => \HeshamFouda\AgGrid\AgGridDefaultExportTimezoneProvider::class ];
使用方法
查询资源
简单地在您的控制器中接受一个AgGridGetRowsRequest
,并返回您要查询的模型的一个AgGridQueryBuilder
实例。过滤、排序和导出将自动为您处理。您还可以将JSON资源传递给查询构建器以包装您的模型。
class FlamingoGridController extends Controller { public function __invoke(AgGridGetRowsRequest $request): AgGridQueryBuilder { $query = Flamingo::query() ->with(['keeper']) ->orderByDesc('id'); return AgGridQueryBuilder::forRequest($request, $query) ->resource(FlamingoResource::class); } }
设置过滤值
当使用AG Grid与serverSide
行模型时,您需要负责提供设置值过滤器的值(前端只知道全部数据的一个子集,因此无法知道所有可能的设置值)。
class FlamingoGridSetValuesController extends Controller { public function __invoke(AgGridSetValuesRequest $request) { $query = Flamingo::query() ->with(['keeper']); return AgGridQueryBuilder::forSetValuesRequest($request, $query) ->toSetValues(['*']); } }
请参阅AgGridSetValuesRequest
类以了解请求的结构。
重要
您需要白名单可以检索设置过滤值的列。这可以通过提供包含列/点关系的数组来完成
->toSetValues(['name', 'kepper.name']);
如果您的模型没有公开任何关系或敏感列,您也可以使用['*']
作为通配符。
以下是前端实现的示例
const colDef = { filterParams: { excelMode: 'windows', values: (parameters: SetFilterValuesFuncParams) => { axios .post('url', { column, filterModel: parameters.api.getFilterModel(), }, ) .then((response) => { parameters.success(response.data) }).catch(() => { parameters.success([]) }) }, }, }
服务器端选择
当使用AG Grid与serverSide
行模型时,在执行批量操作时,您不能只是将选定的ID传递给服务器。在这种情况下,您可以将网格的当前选择状态传递给服务器并在那里解决选择。
为此,请在您的请求中添加以下内容
class FeedFlamingosRequest extends FormRequest { public function rules(): array { return [ 'selection' => ['required', new AgGridSelection()], 'food_type' => ['required', 'string'], ]; } }
在您的控制器中,使用AgGridQueryBuilder
来解决选择
class FeedFlamingosController extends Controller { public function __invoke(FeedFlamingsRequest $request): AgGridQueryBuilder { $flamingos = AgGridQueryBuilder::forSelection($request->validated('selection'))->get(); foreach($flamingos as $flamingo){ $flamingo->feed($request->validated('food_type')); } return $flamingos; } }
导出
要为您的模型启用服务器端导出,您必须实现AgGridExportable
接口。之后,您只需将exportFormat
作为请求的一部分传递给网格控制器,库就会将您的模型转换为Excel、CSV或TSV文件。
class Flamingo extends Model implements AgGridExportable { // ... your model definitions public static function getAgGridColumnDefinitions(): array { return [ new AgGridColumnDefinition( 'id', __('ID'), ), new AgGridColumnDefinition( 'name', __('Name'), ), new AgGridColumnDefinition( 'keeper_id', __('Keeper'), null, fn ($data) => $data->keeper->name, ), new AgGridColumnDefinition( 'created_at', __('Created At'), new AgGridDateFormatter(), ), ]; } }
自定义过滤器
有时您可能需要向查询添加自定义过滤器作用域或其他约束,这些约束超出了标准AG Grid过滤器的范围。在这种情况下,您可以在请求的customFilters
对象中填充您自己的数据。在后端,您的模型必须实现以下所示的AgGridCustomFilterable
接口
class Flamingo extends Model implements AgGridCustomFilterable { use SoftDeletes; // ... your model definitions public function applyAgGridCustomFilters(Builder $query, array $filters): void { $query->when($filters['showTrashed'] ?? false, function ($query) { return $query->withTrashed(); }); } }
类型定义
您可以使用以下TypeScript类型定义作为实现前端请求的参考
interface AgGridSelection { rowModel: 'serverSide' | 'clientSide' selectAll: boolean toggledNodes: (string | number)[] filterModel?: any customFilters?: any } interface AgGridGetRowsRequest extends IServerSideGetRowsRequest { exportFormat?: 'excel' | 'csv' | 'tsv' exportColumns?: string[] customFilters?: any } interface AgGridGetRowsResponse<T> { total: number data: T[] }
前端实现
您可以使用任何前端技术或框架。但是,以下是一些可以作为您自己实现的起点的一些示例
创建数据源
为了使用服务器端行模型,您必须创建一个数据源。以下是一个这样的示例实现
function makeDataSource<T>( url: string, customFilters?: Record<string, any> ): IServerSideDatasource { return { // called by the grid when more rows are required async getRows(parameters) { const request = { ...parameters.request, customFilters, } // get data for request from server try { const response = await axios.post<AgGridGetRowsResponse<T>>(url, request) parameters.success({ rowData: response.data.data, rowCount: response.data.total, }) } catch { parameters.fail() } }, } }
触发服务器端导出
AG Grid默认不实现服务器端导出。但是,您可以在某个位置创建一个自定义上下文菜单或添加一个按钮来触发服务器端导出。处理函数可能看起来像这样
async function exportServerSide(grid: GridApi, format: 'excel' | 'csv' | 'tsv', onlySelected: boolean) { // using a private api here to oget the ssrm parameters const parameters = api.getModel().getRootStore().getSsrmParams() // only request the visible columns const cols = columnApi?.getAllDisplayedColumns().map((column) => column.getColId()) // download the file const response = await axios.post( props.dataSourceUrl!, { ...parameters, ...(onlySelected ? api.getServerSideSelectionState() : {}), exportFormat: format, exportColumns: cols, }, { responseType: 'blob', } ) // create an object url from the response const url = URL.createObjectURL(response.data) // create a link to trigger the download const a = document.createElement('a') a.href = url a.download = true a.click() }
跟踪选择状态
如果您想使用服务器端选择,您必须跟踪网格的当前选择和过滤状态
// use the selection in any batch requests to the server let selection: AgGridSelection function onSelectionChanged(event: SelectionChangedEvent) { if (event.api.getModel().getType() !== 'serverSide') { throw new Error('Only the serverSide row model is supported.') } const selectionState = event.api.getServerSideSelectionState() as IServerSideSelectionState selection = { rowModel: 'serverSide', selectAll: selectionState.selectAll, toggledNodes: selectionState.toggledNodes, filterModel: event.api.getFilterModel() } } function onFilterChanged(event: FilterChangedEvent) { if (!selection) { return } selection.filterModel = event.api.getFilterModel() }
限制
- 由于在设置和JSON查询中使用了一些特殊的SQL运算符,因此只能与PostgreSQL作为存储后端一起使用。
- 不支持每个过滤器有多个条件(AND,OR)
- 不支持AG Grid的Pivot模式的服务器端分组
关系中的值过滤只支持一级。例如,您可以过滤relation.value
,但不能过滤relation.otherRelation.value
待办事项
- 实现嵌套JSON字段的集合过滤器
- 每个过滤器实现多个条件(
AND
,OR
) - 添加类型安全的选型和请求数据结构
- 使用mysql进行测试
变更日志
有关最近变更的更多信息,请参阅变更日志。
贡献
有关详细信息,请参阅贡献指南。
鸣谢
许可协议
MIT许可协议(MIT)。有关更多信息,请参阅许可文件。