Skip to content

Commit

Permalink
Add Custom FIlter Input Attributes, Cleanup Filter Tests (#2131)
Browse files Browse the repository at this point in the history
* Add Custom FIlter Input Attributes, Cleanup Filter Tests

* Fix styling

---------

Co-authored-by: lrljoe <[email protected]>
  • Loading branch information
lrljoe and lrljoe authored Dec 24, 2024
1 parent 493959c commit 4bb6b3d
Show file tree
Hide file tree
Showing 58 changed files with 1,272 additions and 674 deletions.
46 changes: 46 additions & 0 deletions docs/filter-types/filters-number.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,27 @@ weight: 9

Number filters are just HTML number inputs.

```php
public function filters(): array
{
return [
NumberFilter::make('Amount')
->filter(function(Builder $builder, string $value) {
$builder->where('amount', '<', $value);
}),
];
}
```

Historically, min/max/placeholders were set using the "config" option, which is still available. However, it is strongly recommended to use the new setInputAttributes for enhanced customisation.

## Old Behaviour
The following would:
- Set a min of 0
- Set a max of 100
- Add a placeholder
- Keep the default colors & styling

```php
public function filters(): array
{
Expand All @@ -21,3 +42,28 @@ public function filters(): array
];
}
```

## New Behaviour
The following would:
- Set a min of 5
- Set a max of 20
- Set steps to be 0.5
- Add a placeholder
- Keep the default colors & styling

```php
public function filters(): array
{
return [
NumberFilter::make('Age')
->setInputAttributes([
'min' => '5', // Minimum Value Accepted
'max' => '20', // Maximum Value Accepted
'step' => '0.5', // Set step
'placeholder' => 'Enter Number 0 - 100', // A placeholder value
'default-colors' => true,
'default-styling' => true,
]),
];
}
```
52 changes: 52 additions & 0 deletions docs/filters/available-filter-methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,58 @@ TextFilter::make('Name')
),
```

## setInputAttributes
Allows for customising the attributes that will apply to the input field for the filter.

By default, this replaces the default classes on the Filter Input, if you would like to keep them, set the default-styling and/or default-colors flags to true.

### TextFilter Example
The following would:
- Set a maxlength of 75
- Set a placeholder of "Enter a Name"
- Replace the default colors
- Retain the default styling (e.g. rounding/shadow)

```php
public function filters(): array
{
return [
TextFilter::make('Name')
->setInputAttributes([
'maxlength' => '75',
'placeholder' => 'Enter a Name',
'class' => 'text-white bg-red-500 dark:bg-red-500',
'default-colors' => false,
'default-styling' => true,
]),
];
}
```

### NumberFilter Example
The following would:
- Set a min of 5
- Set a max of 20
- Set steps to be 0.5
- Keep the default colors & styling

```php
public function filters(): array
{
return [
NumberFilter::make('Age')
->setInputAttributes([
'min' => '5',
'max' => '20',
'step' => '0.5',
'default-colors' => true,
'default-styling' => true,
]),
];
}
```


## setCustomView
Use a fully custom view for a filter. This will utilise solely your view when rendering this filter. Note that the following methods will no longer apply to a filter using this:
- setCustomFilterLabel
Expand Down
17 changes: 9 additions & 8 deletions resources/views/components/tools/filters/boolean.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@
<x-livewire-tables::tools.filter-label :$filter :$filterLayout :$tableName :$isTailwind :$isBootstrap4 :$isBootstrap5 :$isBootstrap />
<input id="thisId" type="checkbox" name="switch" class="hidden" :checked="value" />

<button id="{{ $tableName }}-filter-{{ $filter->getKey() }}"
x-ref="switchButton"
type="button"
@click="toggleStatusWithUpdate"
:class="(value == 1 || value == true) ? 'bg-blue-600' : 'bg-neutral-200'"
class="relative inline-flex h-6 py-0.5 ml-4 focus:outline-none rounded-full w-10"
x-cloak>
<span :class="(value == 1 || value == true) ? 'translate-x-[18px]' : 'translate-x-0.5'" class="w-5 h-5 duration-200 ease-in-out bg-white rounded-full shadow-md"></span>
<button x-cloak {{ $filterInputAttributes->merge([
":class" => "(value == 1 || value == true) ? '".$filterInputAttributes['activeColor']."' : '".$filterInputAttributes['inactiveColor']."'",
])
->class([
'relative inline-flex h-6 py-0.5 ml-4 focus:outline-none rounded-full w-10' => ($filterInputAttributes['default-styling'] ?? true)
])
->except(['default-styling','default-colors','activeColor','inactiveColor','blobColor'])
}}>
<span :class="(value == 1 || value == true) ? 'translate-x-[18px]' : 'translate-x-0.5'" class="w-5 h-5 duration-200 ease-in-out rounded-full shadow-md {{ $filterInputAttributes['blobColor'] }}"></span>
</button>
<template x-if="(value == 1 || value == true)">
<button @click="toggleStatusWithReset" type="button"
Expand Down
21 changes: 9 additions & 12 deletions resources/views/components/tools/filters/date.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,14 @@
'rounded-md shadow-sm' => $isTailwind,
'mb-3 mb-md-0 input-group' => $isBootstrap,
])>
<input {{ $filter->getWireMethod('filterComponents.'.$filter->getKey()) }}
wire:key="{{ $filter->generateWireKey($tableName, 'date') }}"
id="{{ $tableName }}-filter-{{ $filter->getKey() }}@if($filter->hasCustomPosition())-{{ $filter->getCustomPosition() }}@endif"
type="date"
@if($filter->hasConfig('min')) min="{{ $filter->getConfig('min') }}" @endif
@if($filter->hasConfig('max')) max="{{ $filter->getConfig('max') }}" @endif
@if($filter->hasConfig('placeholder')) placeholder="{{ $filter->getConfig('placeholder') }}" @endif
@class([
'block w-full border-gray-300 rounded-md shadow-sm transition duration-150 ease-in-out focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 dark:bg-gray-800 dark:text-white dark:border-gray-600' => $isTailwind,
'form-control' => $isBootstrap,
])
/>
<input {!! $filter->getWireMethod('filterComponents.'.$filter->getKey()) !!} {{
$filterInputAttributes->merge()
->class([
'block w-full rounded-md shadow-sm transition duration-150 ease-in-out focus:ring focus:ring-opacity-50' => $isTailwind && ($filterInputAttributes['default-styling'] ?? true),
'border-gray-300 focus:border-indigo-300 focus:ring-indigo-200 dark:bg-gray-800 dark:text-white dark:border-gray-600' => $isTailwind && ($filterInputAttributes['default-colors'] ?? true),
'form-control' => $isBootstrap,
])
->except(['default-styling','default-colors'])
}} />
</div>
</div>
21 changes: 9 additions & 12 deletions resources/views/components/tools/filters/datetime.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,14 @@
'rounded-md shadow-sm' => $isTailwind,
'mb-3 mb-md-0 input-group' => $isBootstrap,
])>
<input {{ $filter->getWireMethod('filterComponents.'.$filter->getKey()) }}
wire:key="{{ $filter->generateWireKey($tableName, 'datetime') }}"
id="{{ $tableName }}-filter-{{ $filter->getKey() }}@if($filter->hasCustomPosition())-{{ $filter->getCustomPosition() }}@endif"
type="datetime-local"
@if($filter->hasConfig('min')) min="{{ $filter->getConfig('min') }}" @endif
@if($filter->hasConfig('max')) max="{{ $filter->getConfig('max') }}" @endif
@if($filter->hasConfig('placeholder')) placeholder="{{ $filter->getConfig('placeholder') }}" @endif
@class([
'block w-full border-gray-300 rounded-md shadow-sm transition duration-150 ease-in-out focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 dark:bg-gray-800 dark:text-white dark:border-gray-600' => $isTailwind,
'form-control' => $isBootstrap,
])
/>
<input {!! $filter->getWireMethod('filterComponents.'.$filter->getKey()) !!} {{
$filterInputAttributes->merge()
->class([
'block w-full rounded-md shadow-sm transition duration-150 ease-in-out focus:ring focus:ring-opacity-50' => $isTailwind && ($filterInputAttributes['default-styling'] ?? true),
'border-gray-300 focus:border-indigo-300 focus:ring-indigo-200 dark:bg-gray-800 dark:text-white dark:border-gray-600' => $isTailwind && ($filterInputAttributes['default-colors'] ?? true),
'form-control' => $isBootstrap,
])
->except(['default-styling','default-colors'])
}} />
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,22 @@
<x-livewire-tables::tools.filter-label :$filter :$filterLayout :$tableName :$isTailwind :$isBootstrap4 :$isBootstrap5 :$isBootstrap />

@if ($isTailwind)
<div class="rounded-md shadow-sm">
<select multiple
{{ $filter->getWireMethod('filterComponents.'.$filter->getKey()) }}
wire:key="{{ $filter->generateWireKey($tableName, 'multiselectdropdown') }}"
id="{{ $tableName }}-filter-{{ $filter->getKey() }}@if($filter->hasCustomPosition())-{{ $filter->getCustomPosition() }}@endif"
class="block w-full transition duration-150 ease-in-out border-gray-300 rounded-md shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 dark:bg-gray-800 dark:text-white dark:border-gray-600"
>
@if ($filter->getFirstOption() !== '')
<option @if($filter->isEmpty($this)) selected @endif value="all">{{ $filter->getFirstOption()}}</option>
@endif
@foreach($filter->getOptions() as $key => $value)
@if (is_iterable($value))
<optgroup label="{{ $key }}">
@foreach ($value as $optionKey => $optionValue)
<option value="{{ $optionKey }}">{{ $optionValue }}</option>
@endforeach
</optgroup>
@else
<option value="{{ $key }}">{{ $value }}</option>
@endif
@endforeach
</select>
</div>
@elseif ($isBootstrap)
<div class="rounded-md shadow-sm">
@endif
<select multiple
{{ $filter->getWireMethod("filterComponents.".$filter->getKey()) }}
wire:key="{{ $filter->generateWireKey($tableName, 'multiselectdropdown') }}"
id="{{ $tableName }}-filter-{{ $filter->getKey() }}@if($filter->hasCustomPosition())-{{ $filter->getCustomPosition() }}@endif"
class="{{ $isBootstrap4 ? 'form-control' : 'form-select' }}"
>
@if ($filter->getFirstOption() != "")
{!! $filter->getWireMethod('filterComponents.'.$filter->getKey()) !!} {{
$filterInputAttributes->merge([
'wire:key' => $filter->generateWireKey($tableName, 'multiselectdropdown'),
])
->class([
'block w-full transition duration-150 ease-in-out rounded-md shadow-sm focus:ring focus:ring-opacity-50' => $isTailwind && ($filterInputAttributes['default-styling'] ?? true),
'border-gray-300 focus:border-indigo-300 focus:ring-indigo-200 dark:bg-gray-800 dark:text-white dark:border-gray-600' => $isTailwind && ($filterInputAttributes['default-colors'] ?? true),
'form-control' => $isBootstrap4 && ($filterInputAttributes['default-styling'] ?? true),
'form-select' => $isBootstrap5 && ($filterInputAttributes['default-styling'] ?? true),
])
->except(['default-styling','default-colors'])
}}>
@if ($filter->getFirstOption() !== '')
<option @if($filter->isEmpty($this)) selected @endif value="all">{{ $filter->getFirstOption()}}</option>
@endif
@foreach($filter->getOptions() as $key => $value)
Expand All @@ -47,5 +32,7 @@ class="{{ $isBootstrap4 ? 'form-control' : 'form-select' }}"
@endif
@endforeach
</select>
@if ($isTailwind)
</div>
@endif
</div>
88 changes: 42 additions & 46 deletions resources/views/components/tools/filters/multi-select.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,61 +2,57 @@
<x-livewire-tables::tools.filter-label :$filter :$filterLayout :$tableName :$isTailwind :$isBootstrap4 :$isBootstrap5 :$isBootstrap />

@if ($isTailwind)
<div class="rounded-md shadow-sm">
<div>
<input
type="checkbox"
id="{{ $tableName }}-filter-{{ $filter->getKey() }}-select-all-@if($filter->hasCustomPosition()){{ $filter->getCustomPosition() }}@endif"
wire:input="selectAllFilterOptions('{{ $filter->getKey() }}')"
class="text-indigo-600 rounded border-gray-300 shadow-sm transition duration-150 ease-in-out focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 dark:bg-gray-900 dark:text-white dark:border-gray-600 dark:hover:bg-gray-600 dark:focus:bg-gray-600 disabled:opacity-50 disabled:cursor-wait"
>
<label for="{{ $tableName }}-filter-{{ $filter->getKey() }}-select-all-@if($filter->hasCustomPosition()){{ $filter->getCustomPosition() }}@endif" class="dark:text-white">
<div class="rounded-md shadow-sm">
@endif
<div @class(['form-check' => $isBootstrap])>
<input id="{{ $tableName }}-filter-{{ $filter->getKey() }}-select-all{{ $filter->hasCustomPosition() ? '-'.$filter->getCustomPosition() : null }}" wire:input="selectAllFilterOptions('{{ $filter->getKey() }}')" {{
$filterInputAttributes->merge([
'type' => 'checkbox'
])
->class([
'rounded shadow-sm transition duration-150 ease-in-out focus:ring focus:ring-opacity-50 disabled:opacity-50 disabled:cursor-wait' => $isTailwind && ($filterInputAttributes['default-styling'] ?? true),
'text-indigo-600 border-gray-300 focus:border-indigo-300 focus:ring-indigo-200 dark:bg-gray-900 dark:text-white dark:border-gray-600 dark:hover:bg-gray-600 dark:focus:bg-gray-600 ' => $isTailwind && ($filterInputAttributes['default-colors'] ?? true),
'form-check-input' => $isBootstrap && ($filterInputAttributes['default-styling'] ?? true),
])
->except(['id','wire:key','value','default-styling','default-colors'])
}}>
<label for="{{ $tableName }}-filter-{{ $filter->getKey() }}-select-all{{ $filter->hasCustomPosition() ? '-'.$filter->getCustomPosition() : null }}" @class([
'dark:text-white' => $isTailwind,
'form-check-label' => $isBootstrap,
])>
@if ($filter->getFirstOption() !== '')
{{ $filter->getFirstOption() }}
@else
{{ __($localisationPath.'All') }}
@endif
</label>
</div>

@foreach($filter->getOptions() as $key => $value)
<div wire:key="{{ $tableName }}-filter-{{ $filter->getKey() }}-multiselect-{{ $key }}-@if($filter->hasCustomPosition()){{ $filter->getCustomPosition() }}@endif">
<input
type="checkbox"
id="{{ $tableName }}-filter-{{ $filter->getKey() }}-{{ $loop->index }}-@if($filter->hasCustomPosition()){{ $filter->getCustomPosition() }}@endif"
value="{{ $key }}"
wire:key="{{ $tableName }}-filter-{{ $filter->getKey() }}-{{ $loop->index }}-@if($filter->hasCustomPosition()){{ $filter->getCustomPosition() }}@endif"
{{ $filter->getWireMethod('filterComponents.'.$filter->getKey()) }}
class="text-indigo-600 rounded border-gray-300 shadow-sm transition duration-150 ease-in-out focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 dark:bg-gray-900 dark:text-white dark:border-gray-600 dark:hover:bg-gray-600 dark:focus:bg-gray-600 disabled:opacity-50 disabled:cursor-wait"
>
<label for="{{ $tableName }}-filter-{{ $filter->getKey() }}-{{ $loop->index }}-@if($filter->hasCustomPosition()){{ $filter->getCustomPosition() }}@endif" class="dark:text-white">{{ $value }}</label>
</div>
@endforeach
</div>
@elseif ($isBootstrap)
<div class="form-check">
<input
type="checkbox"
id="{{ $tableName }}-filter-{{ $filter->getKey() }}-select-all-@if($filter->hasCustomPosition()){{ $filter->getCustomPosition() }}@endif"
wire:input="selectAllFilterOptions('{{ $filter->getKey() }}')"
class="form-check-input"
>
<label class="form-check-label" for="{{ $tableName }}-filter-{{ $filter->getKey() }}-@if($filter->hasCustomPosition()){{ $filter->getCustomPosition() }}@endif-select-all">{{ __($localisationPath.'All') }}</label>
</label>
</div>

@foreach($filter->getOptions() as $key => $value)
<div class="form-check" wire:key="{{ $tableName }}-filter-{{ $filter->getKey() }}-multiselect-{{ $key }}-@if($filter->hasCustomPosition()){{ $filter->getCustomPosition() }}@endif">
<input
class="form-check-input"
type="checkbox"
id="{{ $tableName }}-filter-{{ $filter->getKey() }}-{{ $loop->index }}-@if($filter->hasCustomPosition()){{ $filter->getCustomPosition() }}@endif"
value="{{ $key }}"
wire:key="{{ $tableName }}-filter-{{ $filter->getKey() }}-{{ $loop->index }}-@if($filter->hasCustomPosition()){{ $filter->getCustomPosition() }}@endif"
{{ $filter->getWireMethod('filterComponents.'.$filter->getKey()) }}

>
<label class="form-check-label" for="{{ $tableName }}-filter-{{ $filter->getKey() }}-{{ $loop->index }}-@if($filter->hasCustomPosition()){{ $filter->getCustomPosition() }}@endif">{{ $value }}</label>
<div @class([
'form-check' => $isBootstrap,
]) wire:key="{{ $tableName }}-filter-{{ $filter->getKey() }}-multiselect-{{ $key }}{{ $filter->hasCustomPosition() ? '-'.$filter->getCustomPosition() : null }}">
<input {!! $filter->getWireMethod('filterComponents.'.$filter->getKey()) !!}
id="{{ $tableName }}-filter-{{ $filter->getKey() }}-{{ $loop->index }}{{ $filter->hasCustomPosition() ? '-'.$filter->getCustomPosition() : null }}"

wire:key="{{ $tableName }}-filter-{{ $filter->getKey() }}-{{ $loop->index }}{{ $filter->hasCustomPosition() ? '-'.$filter->getCustomPosition() : null }}" value="{{ $key }}" {{
$filterInputAttributes->merge([
'type' => 'checkbox'
])
->class([
'rounded shadow-sm transition duration-150 ease-in-out focus:ring focus:ring-opacity-50 disabled:opacity-50 disabled:cursor-wait' => $isTailwind && ($filterInputAttributes['default-styling'] ?? true),
'text-indigo-600 border-gray-300 focus:border-indigo-300 focus:ring-indigo-200 dark:bg-gray-900 dark:text-white dark:border-gray-600 dark:hover:bg-gray-600 dark:focus:bg-gray-600 ' => $isTailwind && ($filterInputAttributes['default-colors'] ?? true),
'form-check-input' => $isBootstrap && ($filterInputAttributes['default-styling'] ?? true),
])
->except(['id','wire:key','value','default-styling','default-colors'])
}}>
<label for="{{ $tableName }}-filter-{{ $filter->getKey() }}-{{ $loop->index }}{{ $filter->hasCustomPosition() ? '-'.$filter->getCustomPosition() : null }}" @class([
'dark:text-white' => $isTailwind,
'form-check-label' => $isBootstrap,
])>{{ $value }}</label>
</div>
@endforeach
@if ($isTailwind)
</div>
@endif
</div>
Loading

0 comments on commit 4bb6b3d

Please sign in to comment.