main

filamentphp/demo

Last updated at: 29/12/2023 09:43

AddressForm.php

TLDR

The AddressForm.php file is a part of the Demo Projects project and it defines a class called AddressForm. This class extends the Field class from the Filament\Forms\Components namespace. The AddressForm class represents a form for entering address information. It includes methods for setting and saving relationships, getting child components, setting up the form, and getting the relationship name.

Methods

relationship

This method sets the value of the $relationship property in the AddressForm class. It takes a string or a callable as an argument and returns the AddressForm instance.

saveRelationships

This method saves the relationships associated with the AddressForm instance. It retrieves the current state and record, as well as the relationship object. It then checks if the relationship is null, updates the existing address if one exists, or creates a new address if none exists. Finally, it updates the record's touch timestamp.

getChildComponents

This method returns an array of child components for the AddressForm instance. It includes a grid with a country select component, a text input for the street address, and a grid with text inputs for the city, state/province, and zip/postal code.

setUp

This method sets up the AddressForm instance. It calls the parent's setUp method and adds a callback function to be executed after the state is hydrated. The callback function sets the state of the address form based on the relationship value in the record. It also sets the dehydrated property to false.

getRelationship

This method returns the name of the relationship associated with the AddressForm instance. It evaluates the $relationship property using the evaluate method and falls back to the name of the form if the evaluation returns null.

Classes

There are no additional classes in this file.

<?php

namespace App\Forms\Components;

use Filament\Forms;
use Illuminate\Database\Eloquent\Model;
use Squire\Models\Country;

class AddressForm extends Forms\Components\Field
{
    protected string $view = 'filament-forms::components.group';

    public $relationship = null;

    public function relationship(string | callable $relationship): static
    {
        $this->relationship = $relationship;

        return $this;
    }

    public function saveRelationships(): void
    {
        $state = $this->getState();
        $record = $this->getRecord();
        $relationship = $record?->{$this->getRelationship()}();

        if ($relationship === null) {
            return;
        } elseif ($address = $relationship->first()) {
            $address->update($state);
        } else {
            $relationship->updateOrCreate($state);
        }

        $record->touch();
    }

    public function getChildComponents(): array
    {
        return [
            Forms\Components\Grid::make()
                ->schema([
                    Forms\Components\Select::make('country')
                        ->searchable()
                        ->getSearchResultsUsing(fn (string $query) => Country::where('name', 'like', "%{$query}%")->pluck('name', 'id'))
                        ->getOptionLabelUsing(fn ($value): ?string => Country::find($value)?->getAttribute('name')),
                ]),
            Forms\Components\TextInput::make('street')
                ->label('Street address')
                ->maxLength(255),
            Forms\Components\Grid::make(3)
                ->schema([
                    Forms\Components\TextInput::make('city')
                        ->maxLength(255),
                    Forms\Components\TextInput::make('state')
                        ->label('State / Province')
                        ->maxLength(255),
                    Forms\Components\TextInput::make('zip')
                        ->label('Zip / Postal code')
                        ->maxLength(255),
                ]),
        ];
    }

    protected function setUp(): void
    {
        parent::setUp();

        $this->afterStateHydrated(function (AddressForm $component, ?Model $record) {
            $address = $record?->getRelationValue($this->getRelationship());

            $component->state($address ? $address->toArray() : [
                'country' => null,
                'street' => null,
                'city' => null,
                'state' => null,
                'zip' => null,
            ]);
        });

        $this->dehydrated(false);
    }

    public function getRelationship(): string
    {
        return $this->evaluate($this->relationship) ?? $this->getName();
    }
}