Skip to content

Instantly share code, notes, and snippets.

@MACscr
Last active December 23, 2021 16:29
Show Gist options
  • Save MACscr/5181863fc3d9b6e7a878cebfc57ab453 to your computer and use it in GitHub Desktop.
Save MACscr/5181863fc3d9b6e7a878cebfc57ab453 to your computer and use it in GitHub Desktop.
Checkbox Lists Field (WIP) for Filament Admin v2
<?php
namespace Filament\Forms\Components;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Support\Str;
class BelongsToManyCheckboxList extends MultiSelect
{
use Concerns\CanBeInline;
protected $displayColumnName;
protected $relationship;
protected string $view = 'forms.components.checkbox-list';
protected function setUp(): void
{
parent::setUp();
$this->afterStateHydrated(function (BelongsToManyCheckboxList $component): void {
$relationship = $component->getRelationship();
$relatedModels = $relationship->getResults();
if (!$relatedModels) {
return;
}
$component->state(
$relatedModels->pluck(
$relationship->getRelatedKeyName(),
)->toArray(),
);
});
$this->dehydrated(false);
}
public function relationship(string|callable $relationshipName, string|callable $displayColumnName, ?callable $callback = null): static
{
$this->displayColumnName = $displayColumnName;
$this->relationship = $relationshipName;
$this->options(function (BelongsToManyCheckboxList $component) use ($callback): array {
$relationship = $component->getRelationship();
$relationshipQuery = $relationship->getRelated()->orderBy($component->getDisplayColumnName());
if ($callback) {
$relationshipQuery = $callback($relationshipQuery);
}
return $relationshipQuery
->pluck($component->getDisplayColumnName(), $relationship->getRelatedKeyName())
->toArray()
;
});
return $this;
}
public function saveRelationships(): void
{
$this->getRelationship()->sync($this->getState());
}
public function getDisplayColumnName(): string
{
return $this->evaluate($this->displayColumnName);
}
public function getLabel(): string
{
if (null === $this->label) {
return (string) Str::of($this->getRelationshipName())
->before('.')
->kebab()
->replace(['-', '_'], ' ')
->ucfirst()
;
}
return parent::getLabel();
}
public function getRelationship(): BelongsToMany
{
$model = $this->getModel();
if (is_string($model)) {
$model = new $model();
}
return $model->{$this->getRelationshipName()}();
}
public function getRelationshipName(): string
{
return $this->evaluate($this->relationship);
}
}
<x-forms::field-wrapper
:id="$getId()"
:label="$getLabel()"
:label-sr-only="$isLabelHidden()"
:helper-text="$getHelperText()"
:hint="$getHint()"
:required="$isRequired()"
:state-path="$getStatePath()"
>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 items-stretch">
@foreach(collect($getOptions())->chunk(3) as $chunk)
<div>
@foreach($chunk as $id => $category)
<div>
<label for="categories[{{ $id }}]" class="inline-flex items-center">
<input type="checkbox"
name="categories[]"
class=""
value="{{ $id }}"
{{ $applyStateBindingModifiers('wire:model') }}="{{ $getStatePath() }}"
{{ $attributes->merge($getExtraAttributes())->class([
'transition duration-75 rounded shadow-sm focus:border-primary-500 focus:ring-2 focus:ring-primary-500',
'border-gray-300' => ! $errors->has($getStatePath()),
'border-danger-300 ring-danger-500' => $errors->has($getStatePath()),
]) }}
/>
<span class="ml-2">{{ $category }}</span>
</label>
</div>
@endforeach
</div>
@endforeach
</div>
</x-forms::field-wrapper>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment