Registering a grid 

Step 1: Implement GridInterface 

Classes/DataTable/MyRecordsGrid.php
<?php

declare(strict_types=1);

namespace MyVendor\MyExt\DataTable;

use HRR\T3Datatable\Contract\GridInterface;
use HRR\T3Datatable\DataTable\GridDefinition;

final class MyRecordsGrid implements GridInterface
{
    public function getIdentifier(): string
    {
        return 'myext_records';
    }

    public function getTableName(): string
    {
        return 'tx_myext_records';
    }

    public function build(GridDefinition $definition): void
    {
        $definition
            ->addColumn('uid', 'UID', searchable: false, orderable: true)
            ->addColumn('title', 'Title', searchable: true, orderable: true)
            ->addColumn('crdate', 'Created', searchable: false, orderable: true)
            ->setDefaultOrder('crdate', 'DESC')
            ->setPageLength(25)
            ->withDeletedRestriction()
            ->withHiddenRestriction();
    }
}
Copied!

Step 2: Tag in Services.yaml 

Configuration/Services.yaml
services:
  _instanceof:
    HRR\T3Datatable\Contract\GridInterface:
      tags: ['t3datatable.grid']

  MyVendor\MyExt\:
    resource: '../Classes/*'
Copied!

The grid class is auto-registered when it implements GridInterface.

Step 3: Use the grid identifier in JavaScript 

Pass the same identifier to initDataTable():

initDataTable('#my-table', {
  gridIdentifier: 'myext_records',
  columns: [
    { data: 'uid', title: 'UID' },
    { data: 'title', title: 'Title' },
    { data: 'crdate', title: 'Created' },
  ],
});
Copied!

Column rules 

  • Only columns declared in build() can be searched or sorted.
  • Request column names must match the allowlist regex ^[a-zA-Z0-9_.]+$.
  • Use withDeletedRestriction() / withHiddenRestriction() only when the target table has those fields.

Demo reference 

See HRRT3DatatableDemoPagesGrid in this extension for a working pages example.