diff --git a/docs/src/docs/features/filtering.md b/docs/src/docs/features/filtering.md index 924533b0..4aedb8ba 100644 --- a/docs/src/docs/features/filtering.md +++ b/docs/src/docs/features/filtering.md @@ -256,4 +256,130 @@ class DataTableFiltrationListener $event->setFiltrationData($filtrationData); } } -``` \ No newline at end of file +``` + +### Listening for a given data table + +Attach listeners in your data table type to scope them to a single table: + +```php +use Kreyu\Bundle\DataTableBundle\Type\AbstractDataTableType; +use Kreyu\Bundle\DataTableBundle\DataTableBuilderInterface; +use Kreyu\Bundle\DataTableBundle\Event\DataTableEvents; +use Kreyu\Bundle\DataTableBundle\Event\DataTableFiltrationEvent; + +class ProductDataTableType extends AbstractDataTableType +{ + public function buildDataTable(DataTableBuilderInterface $builder, array $options): void + { + $builder->addEventListener(DataTableEvents::PRE_FILTER, function (DataTableFiltrationEvent $event) { + $data = $event->getFiltrationData(); + // mutate $data as needed, then persist it back + $event->setFiltrationData($data); + }); + } +} +``` + +Alternatively, use an event subscriber and add it to the builder: + +```php +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Kreyu\Bundle\DataTableBundle\Event\DataTableEvents; +use Kreyu\Bundle\DataTableBundle\Event\DataTableFiltrationEvent; + +final class ProductFiltrationSubscriber implements EventSubscriberInterface +{ + public static function getSubscribedEvents(): array + { + return [DataTableEvents::PRE_FILTER => 'onPreFilter']; + } + + public function onPreFilter(DataTableFiltrationEvent $event): void + { + $event->setFiltrationData($event->getFiltrationData()); + } +} + +class ProductDataTableType extends AbstractDataTableType +{ + public function __construct(private readonly ProductFiltrationSubscriber $subscriber) {} + + public function buildDataTable(DataTableBuilderInterface $builder, array $options): void + { + $builder->addEventSubscriber($this->subscriber); + } +} +``` + +### Listening globally (all data tables) + +Use a DataTable type extension to register a listener for every table: + +```php +use Kreyu\Bundle\DataTableBundle\Extension\AbstractDataTableTypeExtension; +use Kreyu\Bundle\DataTableBundle\Type\DataTableType; +use Kreyu\Bundle\DataTableBundle\DataTableBuilderInterface; +use Kreyu\Bundle\DataTableBundle\Event\DataTableEvents; +use App\Listener\DataTableFiltrationListener; // invokable class from above + +final class AppDataTableFiltrationExtension extends AbstractDataTableTypeExtension +{ + public function __construct(private readonly DataTableFiltrationListener $listener) {} + + public static function getExtendedTypes(): iterable + { + return [DataTableType::class]; + } + + public function buildDataTable(DataTableBuilderInterface $builder, array $options): void + { + $builder->addEventListener(DataTableEvents::PRE_FILTER, [$this->listener, '__invoke']); + } +} +``` + +Or wire a subscriber globally via the type extension: + +```php +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Kreyu\Bundle\DataTableBundle\Event\DataTableEvents; +use Kreyu\Bundle\DataTableBundle\Event\DataTableFiltrationEvent; + +final class GlobalFiltrationSubscriber implements EventSubscriberInterface +{ + public static function getSubscribedEvents(): array + { + return [DataTableEvents::PRE_FILTER => 'onPreFilter']; + } + + public function onPreFilter(DataTableFiltrationEvent $event): void + { + // global filtration logic + } +} + +final class AppDataTableFiltrationExtension extends AbstractDataTableTypeExtension +{ + public function __construct(private readonly GlobalFiltrationSubscriber $subscriber) {} + + public function buildDataTable(DataTableBuilderInterface $builder, array $options): void + { + $builder->addEventSubscriber($this->subscriber); + } +} +``` + +Register the extension as a service with autoconfiguration so it’s discovered automatically: + +```yaml +# config/services.yaml +services: + App\DataTable\AppDataTableFiltrationExtension: + autowire: true + autoconfigure: true +``` + +::: warning +Data table events are dispatched on a per-table dispatcher. Using `#[AsEventListener]` on a service that listens on Symfony’s global dispatcher will not receive these events — add listeners via the builder or a type extension as shown above. +::: diff --git a/docs/src/docs/features/pagination.md b/docs/src/docs/features/pagination.md index d2a90679..307ed058 100644 --- a/docs/src/docs/features/pagination.md +++ b/docs/src/docs/features/pagination.md @@ -307,6 +307,67 @@ Can be used to execute additional logic after the pagination is applied. The dispatched events are instance of the [`DataTablePaginationEvent`](https://github.com/Kreyu/data-table-bundle/blob/main/src/Event/DataTablePaginationEvent.php): +### Listening for a given data table + +Attach listeners directly in your data table type using the builder. This scopes the listener to that single table: + +```php +use Kreyu\Bundle\DataTableBundle\Type\AbstractDataTableType; +use Kreyu\Bundle\DataTableBundle\DataTableBuilderInterface; +use Kreyu\Bundle\DataTableBundle\Event\DataTableEvents; +use Kreyu\Bundle\DataTableBundle\Event\DataTablePaginationEvent; + +class ProductDataTableType extends AbstractDataTableType +{ + public function buildDataTable(DataTableBuilderInterface $builder, array $options): void + { + $builder->addEventListener(DataTableEvents::PRE_PAGINATE, function (DataTablePaginationEvent $event) { + $data = $event->getPaginationData(); + // mutate $data as needed, then persist it back + $event->setPaginationData($data); + }); + } +} +``` + +Alternatively, use an event subscriber and add it to the builder: + +```php +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Kreyu\Bundle\DataTableBundle\Event\DataTableEvents; +use Kreyu\Bundle\DataTableBundle\Event\DataTablePaginationEvent; + +final class ProductPaginationSubscriber implements EventSubscriberInterface +{ + public static function getSubscribedEvents(): array + { + return [ + DataTableEvents::PRE_PAGINATE => 'onPrePaginate', + ]; + } + + public function onPrePaginate(DataTablePaginationEvent $event): void + { + // mutate pagination data as needed + $event->setPaginationData($event->getPaginationData()); + } +} + +class ProductDataTableType extends AbstractDataTableType +{ + public function __construct(private readonly ProductPaginationSubscriber $subscriber) {} + + public function buildDataTable(DataTableBuilderInterface $builder, array $options): void + { + $builder->addEventSubscriber($this->subscriber); + } +} +``` + +### Listening globally (all data tables) + +To react for every data table, add a DataTable type extension and register a listener there: + ```php use Kreyu\Bundle\DataTableBundle\Event\DataTablePaginationEvent; @@ -322,3 +383,71 @@ class DataTablePaginationListener } } ``` + +```php +use Kreyu\Bundle\DataTableBundle\Extension\AbstractDataTableTypeExtension; +use Kreyu\Bundle\DataTableBundle\Type\DataTableType; +use Kreyu\Bundle\DataTableBundle\DataTableBuilderInterface; +use Kreyu\Bundle\DataTableBundle\Event\DataTableEvents; +use App\Listener\DataTablePaginationListener; + +final class AppDataTablePaginationExtension extends AbstractDataTableTypeExtension +{ + public function __construct(private readonly DataTablePaginationListener $listener) {} + + public static function getExtendedTypes(): iterable + { + return [DataTableType::class]; + } + + public function buildDataTable(DataTableBuilderInterface $builder, array $options): void + { + $builder->addEventListener(DataTableEvents::PRE_PAGINATE, [$this->listener, '__invoke']); + } +} +``` + +Or wire a subscriber globally via the type extension: + +```php +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Kreyu\Bundle\DataTableBundle\Event\DataTableEvents; +use Kreyu\Bundle\DataTableBundle\Event\DataTablePaginationEvent; + +final class GlobalPaginationSubscriber implements EventSubscriberInterface +{ + public static function getSubscribedEvents(): array + { + return [DataTableEvents::PRE_PAGINATE => 'onPrePaginate']; + } + + public function onPrePaginate(DataTablePaginationEvent $event): void + { + // global logic for all data tables + } +} + +final class AppDataTablePaginationExtension extends AbstractDataTableTypeExtension +{ + public function __construct(private readonly GlobalPaginationSubscriber $subscriber) {} + + public function buildDataTable(DataTableBuilderInterface $builder, array $options): void + { + $builder->addEventSubscriber($this->subscriber); + } +} +``` + +Register the extension as a service with autoconfiguration so it’s discovered automatically: + +```yaml +# config/services.yaml +services: + App\DataTable\AppDataTablePaginationExtension: + autowire: true + autoconfigure: true +``` + +::: warning +Data table events are dispatched on a per-table dispatcher. Using `#[AsEventListener]` on a service that listens on Symfony’s global dispatcher will not receive these events — add listeners via the builder or a type extension as shown above. +::: diff --git a/docs/src/docs/features/sorting.md b/docs/src/docs/features/sorting.md index 4a7459d7..4f3873c6 100644 --- a/docs/src/docs/features/sorting.md +++ b/docs/src/docs/features/sorting.md @@ -406,3 +406,129 @@ class DataTableSortingListener } } ``` + +### Listening for a given data table + +Attach listeners in your data table type to scope them to a single table: + +```php +use Kreyu\Bundle\DataTableBundle\Type\AbstractDataTableType; +use Kreyu\Bundle\DataTableBundle\DataTableBuilderInterface; +use Kreyu\Bundle\DataTableBundle\Event\DataTableEvents; +use Kreyu\Bundle\DataTableBundle\Event\DataTableSortingEvent; + +class ProductDataTableType extends AbstractDataTableType +{ + public function buildDataTable(DataTableBuilderInterface $builder, array $options): void + { + $builder->addEventListener(DataTableEvents::PRE_SORT, function (DataTableSortingEvent $event) { + $data = $event->getSortingData(); + // mutate $data as needed, then persist it back + $event->setSortingData($data); + }); + } +} +``` + +Alternatively, use an event subscriber and add it to the builder: + +```php +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Kreyu\Bundle\DataTableBundle\Event\DataTableEvents; +use Kreyu\Bundle\DataTableBundle\Event\DataTableSortingEvent; + +final class ProductSortingSubscriber implements EventSubscriberInterface +{ + public static function getSubscribedEvents(): array + { + return [DataTableEvents::PRE_SORT => 'onPreSort']; + } + + public function onPreSort(DataTableSortingEvent $event): void + { + $event->setSortingData($event->getSortingData()); + } +} + +class ProductDataTableType extends AbstractDataTableType +{ + public function __construct(private readonly ProductSortingSubscriber $subscriber) {} + + public function buildDataTable(DataTableBuilderInterface $builder, array $options): void + { + $builder->addEventSubscriber($this->subscriber); + } +} +``` + +### Listening globally (all data tables) + +Use a DataTable type extension to register a listener for every table: + +```php +use Kreyu\Bundle\DataTableBundle\Extension\AbstractDataTableTypeExtension; +use Kreyu\Bundle\DataTableBundle\Type\DataTableType; +use Kreyu\Bundle\DataTableBundle\DataTableBuilderInterface; +use Kreyu\Bundle\DataTableBundle\Event\DataTableEvents; +use App\Listener\DataTableSortingListener; // invokable class from above + +final class AppDataTableSortingExtension extends AbstractDataTableTypeExtension +{ + public function __construct(private readonly DataTableSortingListener $listener) {} + + public static function getExtendedTypes(): iterable + { + return [DataTableType::class]; + } + + public function buildDataTable(DataTableBuilderInterface $builder, array $options): void + { + $builder->addEventListener(DataTableEvents::PRE_SORT, [$this->listener, '__invoke']); + } +} +``` + +Or wire a subscriber globally via the type extension: + +```php +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Kreyu\Bundle\DataTableBundle\Event\DataTableEvents; +use Kreyu\Bundle\DataTableBundle\Event\DataTableSortingEvent; + +final class GlobalSortingSubscriber implements EventSubscriberInterface +{ + public static function getSubscribedEvents(): array + { + return [DataTableEvents::PRE_SORT => 'onPreSort']; + } + + public function onPreSort(DataTableSortingEvent $event): void + { + // global sorting logic + } +} + +final class AppDataTableSortingExtension extends AbstractDataTableTypeExtension +{ + public function __construct(private readonly GlobalSortingSubscriber $subscriber) {} + + public function buildDataTable(DataTableBuilderInterface $builder, array $options): void + { + $builder->addEventSubscriber($this->subscriber); + } +} +``` + +Register the extension as a service with autoconfiguration so it’s discovered automatically: + +```yaml +# config/services.yaml +services: + App\DataTable\AppDataTableSortingExtension: + autowire: true + autoconfigure: true +``` + +::: warning +Data table events are dispatched on a per-table dispatcher. Using `#[AsEventListener]` on a service that listens on Symfony’s global dispatcher will not receive these events — add listeners via the builder or a type extension as shown above. +:::