How to Create a Custom Column for Filament Admin Panel

Filament admin panel has a few useful column types we can use in a table:

  • TextColumn
  • ImageColumn
  • SelectColumn


and more.

if you need a type of column that is not available in filament by default, you can create it yourself.

Here we are going to make a column that shows a very simple progress bar.

Install Filament in a Laravel App

inside a laravel app install Filament with composer:

composer require filament/filament:"^2.0"

if you don’t have a user in database create one:

php artisan make:filament-user

Create a Filament Resource

For this example I create a BookResource to have a table that shows a list of books.

php artisan make:filament-resource Book

Create a Database table with Fake Data

we need to create a model and a database table.

php artisan make:model Book
php artisan make:migration create_books_table

migration file:

   public function up()
    {
        Schema::create('books', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->integer('translation_progress')->default(0);
            $table->string('author');
            $table->string('description');
            $table->string('isbn');
            $table->string('publish_year');
            $table->decimal('price');
            $table->timestamps();
        });
    }

there is a column in the migration called “translation_progress” which we use to show the percentage of the books translation progress in the admin panel.

then we fill the table with fake data to have something to work with.

create a factory:

php artisan make:factory BookFactory
//BookFactory.php

  public function definition()
    {
        return [
            'title' => $this->faker->word(),
            'translation_progress' => random_int(0, 100),
            'author' => $this->faker->name(),
            'description' => $this->faker->sentence(),
            'isbn' => $this->faker->ean13(),
            'publish_year' => $this->faker->year(),
            'price' => $this->faker->numberBetween(20, 500),
        ];
    }

create a seeder:

php artisan make:seeder BookSeeder
//BookSeeder.php
use App\Models\Book;

  public function run()
    {
        Book::factory(20)->create();
    }

and finally run the seeder to fill the database with 20 rows of fake books data.

php artisan db:seed --class=BookSeeder

Run table-column artisan command

now we have a table of books and it is time to create the custom column.

to create a custom column run this artisan command:

php artisan make:table-column ProgressBar

a Class named “ProgressBar.php ” will be created in “app\Tables\Columns“.

<?php

namespace App\Tables\Columns;

use Filament\Tables\Columns\Column;

class ProgressBar extends Column
{
    protected string $view = 'tables.columns.progress-bar';

}

also a blade file named “progress-bar.blade.php file will be created in “resources/views/tables/columns”.

in the blade file we write a simple progress bar code using tailwind.

<div>

    <div class="bg-gray-300 h-4 w-20">
        <div class="bg-green-500 h-full" style="width: 30%"></div>
    </div>

</div>

now in the resource file we have to use the custom column in the table() method.

use App\Tables\Columns\ProgressBar;
   
 public static function table(Table $table): Table
    {

        return $table
            ->columns([
                Tables\Columns\TextColumn::make('title'),
                ProgressBar::make('translated'),
                Tables\Columns\TextColumn::make('author'),
                Tables\Columns\TextColumn::make('publish_year'),
                Tables\Columns\TextColumn::make('price'),
            ])->defaultSort('created_at', 'desc')
            ->filters([
                //
            ])
            ->actions([
                Tables\Actions\EditAction::make(),
            ])
            ->bulkActions([
                Tables\Actions\DeleteBulkAction::make(),
            ]);
    }

by default after using the column we have to see the view content in the table but we don’t.

because tailwind classed are not known in these view files. first we have to use the Filament guid for changing appearance to install and include tailwind here.

install tailwind

run this to install tailwind

npm install tailwindcss @tailwindcss/forms @tailwindcss/typography autoprefixer tippy.js --save-dev

create the tailwind.config.js:

npx tailwindcss init

in tailwind.config.js write this to define colors,forms and typography plugins and most importantly define tailwind for component files in resources folder.

import colors from 'tailwindcss/colors' 
import forms from '@tailwindcss/forms'
import typography from '@tailwindcss/typography' 
 
export default {
    content: [
        './resources/**/*.blade.php',
        './vendor/filament/**/*.blade.php', 
    ],
    darkMode: 'class',
    theme: {
        extend: {
            colors: { 
                danger: colors.rose,
                primary: colors.blue,
                success: colors.green,
                warning: colors.yellow,
            }, 
        },
    },
    plugins: [
        forms, 
        typography, 
    ],
}

for compiling assets i use laravel mix so first we install it:

npm install laravel-mix@latest --save-dev

after that in webpack.mix.js we register tailwind like this:

const mix = require('laravel-mix');

mix.js('resources/js/app.js', 'public/js')
    .postCss('resources/css/filament.css', 'public/css', [
        require('tailwindcss'),
    ]);

make sure you have filament.css file in resources/css.

put this in this file:

@import '../../vendor/filament/filament/resources/css/app.css';

then register filament.css in a service provider:

   public function boot()
    {
        Filament::serving(function () {

                 Filament::registerTheme(
                mix('css/filament.css'),
            );
        });
    }

finally compile the assets:

npx mix

now take look at the table again it should show the progress bar correctly.

here we set the percentage manually on 30% but we have to make it dynmic.

in the component view we have access to $getRecord variable which gives us access to the current record in database. Since we defined “translation_progress” column in databse to have the percentage number we can use it here.

so the view will be like this:

<div>

    <div class="bg-gray-300 h-4 w-20">
        <div class="bg-green-500 h-full" style="width: {{$getRecord()->translation_progress}}%"></div>
    </div>


</div>

we replaced the percentage with $getRecord()->translation_progress to have a dynamic progress bar.

Final Result:

Every record has its own progress percentage.

To summerize creating a custom column in Filament:

  • we install filament in a laravel app
  • run make:table-column artisan command
  • install, register and compile tailwindcss.
  • write your custom view in the column view file.
  • use the Column in table() method inside a resource class.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *