Using Repeater Fields in Laravel Filament

Laravel Eloquent, a powerful and expressive ORM (Object-Relational Mapping) for Laravel, combined with Filament, a Laravel-based admin panel, provides a seamless solution for handling complex data structures. In this blog post, we’ll explore how to store and manage multiple email addresses and phone numbers for a contact using Eloquent and present them in a Filament table.

Database Setup with Laravel Eloquent

To begin with, let’s set up our database table using Laravel migrations. We want to store client information, including their name, phone numbers, and emails. In our migration file, we define the clients table with JSON columns for phone_numbers and emails:

public function up(): void
{
    Schema::create('clients', function (Blueprint $table) {
        $table->string('name');
        $table->json('phone_numbers');
        $table->json('emails');
        $table->id();
        $table->timestamps();
    });
}

To ensure Laravel understands these JSON columns, we cast them to arrays in the model:

protected $casts = [
    'phone_numbers' => 'array',
    'emails' => 'array',
];

Filament Forms for Easy Data Entry

Now, let’s leverage Filament to create user-friendly forms for data entry. We’ll use a repeater field for emails and a more structured repeater for phone numbers, allowing users to specify the type (Home, Work, Mobile) for each number:

public static function form(Form $form): Form
{
    return $form
        ->schema([
            // ... Other form components
            TableRepeater::make('phone_numbers')
                ->schema([
                    Select::make('type')
                        ->options([
                            'home' => 'Home',
                            'work' => 'Work',
                            'mobile' => 'Mobile',
                        ])
                        ->hiddenLabel()
                        ->required(),
                    TextInput::make('number')
                        ->mask('(999) 999-9999')
                        ->tel()
                        ->hiddenLabel()
                        ->required(),
                ]),
            Repeater::make('emails')
                ->simple(
                    TextInput::make('email')
                        ->email()
                        ->distinct()
                        ->required(),
                ),
        ]);
}

To use this example, you will need to install Adam Weston’s Table Repeater plugin:

composer require awcodes/filament-table-repeater

Using Accessors for Data Presentation

To enhance the display of our data, we use accessor methods in our model. These methods allow us to transform raw data into a more readable format. For example, we can create an accessor to retrieve the first phone number with its type as a string:

public function getFirstPhoneNumberAttribute()
{
    return $this->phone_numbers[0]['number'] . ' - ' . ucwords($this->phone_numbers[0]['type']) ?? null;
}

Similarly, we can create an accessor for the first email:

public function getFirstEmailAttribute()
{
    return $this->emails[0] ?? null;
}

Displaying Data in Filament Tables

Finally, let’s showcase our contact data in a Filament table. We include the name, the formatted first phone number, and the first email:

public static function table(Table $table): Table
{
    return $table
        ->columns([
            // ... Other table columns
            TextColumn::make('first_phone_number')
                ->label('Phone Number'),
            TextColumn::make('first_email')
                ->label('Email'),
            // ... Other table columns
        ])
        ->filters([
            // ... Table filters
        ])
        ->actions([
            // ... Table actions
        ])
        ->bulkActions([
            // ... Bulk actions
        ]);
}

In conclusion, combining Laravel Eloquent with Filament provides a robust solution for managing and presenting contact data efficiently. With JSON columns, repeater fields, and accessor methods, handling complex data structures becomes a breeze. Whether you’re a seasoned developer or just getting started, these tools make database management in Laravel a delightful experience.