Ryan Chandler

Building a custom color palette field in Filament - Part 0

1 min read

This post was published 2 years ago. Some of the information might be outdated!

In this short series of blog posts, I'll show you how to create a custom Filament field.

The field we'll be building is a color palette field that lets you select a color from a fixed list of options. Such a simple field will cover the basics of rendering a field and syncing the selected option with the property on the form itself.

Here's an example of the field's API:

ColorPalette::make('color')
    ->options([
        '#ffffff' => 'White',
        '#000000' => 'Black',
    ]),

The color options will be an array of colors and labels. The label will be used to show a tooltip when hovering over the chosen color and the color value itself will be used to render the option.

Generating the boilerplate

To generate an empty field, run the php artisan make:form-field command.

$ php artisan make:form-field

Name (e.g. `RangeSlider`):
> ColorPalette

Successfully created ColorPalette!

This command is provided by the filament/forms package and will generate a basic Field class and corresponding Blade view.

Open up the new app/Forms/Components/ColorPalette.php file and you should see this:

<?php

namespace App\Forms\Components;

use Filament\Forms\Components\Field;

class ColorPalette extends Field
{
    protected string $view = 'forms.components.color-palette';
}

The field is already setup to render a particular Blade view, so let's also take a look at that.

<x-forms::field-wrapper
    :id="$getId()"
    :label="$getLabel()"
    :label-sr-only="$isLabelHidden()"
    :helper-text="$getHelperText()"
    :hint="$getHint()"
    :hint-icon="$getHintIcon()"
    :required="$isRequired()"
    :state-path="$getStatePath()"
>
    <div x-data="{ state: $wire.entangle('{{ $getStatePath() }}') }">
        <!-- Interact with the `state` property in Alpine.js -->
    </div>
</x-forms::field-wrapper>

The boilerplate code inside of the Blade view might be a bit overwhelming at first, but it's actually Filament doing a lot of the heavy lifting for us. It's configuring the field wrapper (the component that renders the label, helper text, etc) and also gives us a basic Alpine component with the field's property already "entangled".

If we render this almost empty field inside of a form, you'll see something like this.

In the next part, we'll add a method to the field that accepts an array of options and start rendering some option buttons to the front-end.