Skip to content

Commit

Permalink
BETA - Livewire Component Filter (#1604)
Browse files Browse the repository at this point in the history
* Initial Commit

---------

Co-authored-by: lrljoe <lrljoe@users.noreply.github.com>
  • Loading branch information
lrljoe and lrljoe committed Dec 21, 2023
1 parent a51d666 commit 4dd0716
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 0 deletions.
102 changes: 102 additions & 0 deletions docs/filter-types/filters-livewire-component.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
---
title: Livewire Custom Filter (Beta)
weight: 11
---

## Livewire Custom Filter

**IN BETA**
This feature is currently in beta, and use in production is not recommended.

### Usage
This allows you to use a child/nested Livewire Component in place of the existing Filters, giving you more control over the look/feel/behaviour of a filter.

To use a LivewireComponentFilter, you must include it in your namespace:
```php
use Rappasoft\LaravelLivewireTables\Views\Filters\LivewireComponentFilter;
```

When creating a filter:
- Specify a unique name
- Set the path to a valid Livewire Component
- Define a filter() callback to define how the returned value will be used.

```php
public function filters(): array
{
return [
LivewireComponentFilter::make('My External Filter')
->setLivewireComponent('my-test-external-filter')
->filter(function (Builder $builder, string $value) {
$builder->where('name', 'like', '%'.$value.'%');
}),
];
}
```

### Configuring Your Livewire Filter Component

A basic example (replicating the Text Filter) looks like the below, note the usage of the "IsExternalFilter" trait.
```php
<?php

namespace App\Livewire;

use Livewire\Component;
use Rappasoft\LaravelLivewireTables\Views\Traits\IsExternalFilter;

class MyTestExternalFilter extends Component
{
use IsExternalFilter;

public function render()
{
return view('livewire.my-test-external-filter');
}
}
```

Should you prefer not to use the IsExternalFilter trait, the below contains all relevant code:
```php
<?php

namespace App\Livewire;

use Livewire\Component;
use Livewire\Attributes\Modelable;

class MyTestExternalFilter extends Component
{
#[Modelable]
public $value = '';

public $filterKey = '';

public function render()
{
return view('livewire.my-test-external-filter');
}
}
```


### Important Notes for Livewire Component Filter Blade
- You must update the "value" property on your component in order to return a value to the DataTableComponent. This is setup via the "IsExternalFilter" trait.
- You should use "debounce" rather than "live" to avoid repetitive updates to the DataTableComponent

An example "my-test-external-filter.blade.php" is given below:
```php
<div role="menuitem">
<div class="rounded-md shadow-sm" >
<input wire:model.debounce.1000ms="value"
type="text"
id="my_test_external_filter_input"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder=""
>
</div>
</div>
```

### Important Notes For The livewire-component-filter.blade.php
- It is **strongly** recommmended not to publish, nor update this file, while this feature is in beta, as it is subject to change at short notice, which may lead to breaking changes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<div wire:key="filterComponents.{{ $filter->getKey() }}-wrapper">
<x-livewire-tables::tools.filter-label :$filter :$filterLayout :$tableName :$isTailwind :$isBootstrap4 :$isBootstrap5 :$isBootstrap />

<livewire:dynamic-component :is="$livewireComponent" :filterKey="$filter->getKey()" :key="'filterComponents-'.$filter->getKey()" wire:model.live="filterComponents.{{ $filter->getKey() }}" />
</div>
65 changes: 65 additions & 0 deletions src/Views/Filters/LivewireComponentFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

namespace Rappasoft\LaravelLivewireTables\Views\Filters;

use Rappasoft\LaravelLivewireTables\Exceptions\DataTableConfigurationException;
use Rappasoft\LaravelLivewireTables\Views\Filter;

class LivewireComponentFilter extends Filter
{
public string $viewPath = 'livewire-tables::components.tools.filters.livewire-component-filter';

public string $livewireComponent = '';

public function validate(string $value): string|bool
{
return $value;
}

public function isEmpty(?string $value): bool
{
return is_null($value) || $value === '';
}

/**
* Gets the Default Value for this Filter via the Component
*/
public function getFilterDefaultValue(): ?string
{
return $this->filterDefaultValue ?? null;
}

public function setLivewireComponent(string $livewireComponent): self
{

$class = '\\'.config('livewire.class_namespace').'\\'.collect(str($livewireComponent)->explode('.'))->map(fn ($segment) => (string) str($segment)->studly())->join('\\');

if (! class_exists($class)) {
throw new DataTableConfigurationException('You must specify a valid path to your Livewire Component Filter.');
}

if (! is_subclass_of($class, \Livewire\Component::class)) {
throw new DataTableConfigurationException('Your Livewire Component Filter MUST Extend Livewire\Component.');
}

$this->livewireComponent = $livewireComponent;

return $this;
}

public function getLivewireComponent(): string
{
return $this->livewireComponent ?? '';
}

public function render(): string|\Illuminate\Contracts\Foundation\Application|\Illuminate\View\View|\Illuminate\View\Factory
{
if ($this->livewireComponent == '') {
throw new DataTableConfigurationException('You must specify a valid path to your Livewire Component Filter.');
}

return view($this->getViewPath(), $this->getFilterDisplayData())->with([
'livewireComponent' => $this->livewireComponent,
]);
}
}
13 changes: 13 additions & 0 deletions src/Views/Traits/IsExternalFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace Rappasoft\LaravelLivewireTables\Views\Traits;

use Livewire\Attributes\Modelable;

trait IsExternalFilter
{
#[Modelable]
public $value = '';

public $filterKey = '';
}

0 comments on commit 4dd0716

Please sign in to comment.