Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Fzoltan87's avatar

Filament 3 Custom Page with multi form in tabs

How can I make my three different forms appear under three separate tabs? Where should I place the tabs and the forms associated with each tab?

They would like to achieve this appearance: Tab1 -> $this->settingForm Tab2 -> $this->emailForm Tab3 -> $this->themeForm

My Code: class PageSettings extends Page implements HasForms { use InteractsWithForms;

protected static ?string $navigationIcon = 'heroicon-o-document-text';

protected static string $view = 'filament.pages.page-setting';

public function getTitle(): string | Htmlable
{
    return __('module_names.page_setting_label');
}

// public static function getNavigationGroup(): string
// {
//   return __('module_names.navigation_groups.pagesfix');
// }

public static function getNavigationLabel(): string
{
    return __('module_names.page_setting_label');
}

public function getHeading(): string
{
    return __('module_names.page_setting_label');
}

public ?array $data_setting = [];
public ?array $data_setting_email = [];
public ?array $data_setting_theme = [];

public function mount(): void
{
    // $this->form->fill($this->getSetting());
    $this->fillForms();
}


protected function getForms(): array
{
    return [
        'settingForm',
        'emailForm',
        'themeForm',
    ];
}

public function settingForm(Form $form): Form
{
    return $form
        ->schema([
            TextInput::make('app_name')
                ->label(__('fields.settings.app_name'))
                ->required(),

            Fieldset::make('Google Analytics')->schema([
                Select::make('google_analytic_status')
                    ->label(__('fields.settings.google_analytic_status'))
                    ->placeholder('Selected'),

                TextInput::make('google_analytic_id')
                    ->label(__('fields.settings.google_analytic_id'))
                    ->required(),
            ])->columns(3),

            Fieldset::make('Social')->schema([
                TextInput::make('social_link_fc')
                    ->label(__('fields.settings.social_link_fc'))
                    ->prefix('https://')
                    ->suffixIcon('heroicon-m-globe-alt')
                    ->required(),

                TextInput::make('social_link_insta')
                    ->label(__('fields.settings.social_link_insta'))
                    ->prefix('https://')
                    ->suffixIcon('heroicon-m-globe-alt')
                    ->required(),

                TextInput::make('social_link_tiktok')
                    ->label(__('fields.settings.social_link_tiktok'))
                    ->prefix('https://')
                    ->suffixIcon('heroicon-m-globe-alt')
                    ->required(),
            ])->columns(3),
        ])
        ->model($this->getSetting())
        ->statePath('data_setting');
}

public function emailForm(Form $form): Form
{
    return $form
        ->schema([
            TextInput::make('email_host')
                ->label(__('fields.settings.email_host'))
                ->required(),

            TextInput::make('email_email')
                ->label(__('fields.settings.email_email'))
                ->required(),

            TextInput::make('email_smtp_user')
                ->label(__('fields.settings.email_smtp_user'))
                ->required(),

            TextInput::make('email_smtp_password')
                ->label(__('fields.settings.email_smtp_password'))
                ->required(),

            TextInput::make('email_port')
                ->label(__('fields.settings.email_port'))
                ->required(),
        ])
        ->model($this->getEmailSetting())
        ->statePath('data_setting_email');
}

public function themeForm(Form $form): Form
{
    return $form
        ->schema([
            Grid::make()->schema([
                ColorPicker::make('cookie_consent_bg_color')
                    ->label(__('fields.settings.cookie_consent_bg_color'))
                    ->required(),

                ColorPicker::make('cookie_consent_b_color')
                    ->label(__('fields.settings.cookie_consent_b_color'))
                    ->required(),

                ColorPicker::make('cookie_consent_btn_color')
                    ->label(__('fields.settings.cookie_consent_btn_color'))
                    ->required(),

                ColorPicker::make('cookie_consent_btn_text_color')
                    ->label(__('fields.settings.cookie_consent_btn_text_color'))
                    ->required(),

                ColorPicker::make('cookie_consent_text_color')
                    ->label(__('fields.settings.cookie_consent_text_color'))
                    ->required(),
            ])->columns(5),

            Grid::make()->schema([
                TextInput::make('cookie_consent_link_text')
                    ->label(__('fields.settings.cookie_consent_link_text'))
                    ->required(),

                TextInput::make('cookie_consent_btn_text')
                    ->label(__('fields.settings.cookie_consent_btn_text'))
                    ->required(),
            ])->columns(2),

            Textarea::make('cookie_consent_msg')
                ->label(__('fields.settings.cookie_consent_msg'))
                ->rows(5)
                ->columnSpanFull(),

            Fieldset::make('Lapozás')->schema([
                TextInput::make('pagination_blog')
                    ->label(__('fields.settings.pagination_blog'))
                    ->suffix(new HtmlString(__('fields.quantity')))
                    ->required(),

                TextInput::make('pagination_comment')
                    ->label(__('fields.settings.pagination_comment'))
                    ->suffix(new HtmlString(__('fields.quantity')))
                    ->required(),

                TextInput::make('pagination_property')
                    ->label(__('fields.settings.pagination_property'))
                    ->suffix(new HtmlString(__('fields.quantity')))
                    ->required(),
            ])->columns(3),

            Fieldset::make('Lábléc')->schema([
                TextInput::make('footer_email')
                    ->label(__('fields.settings.footer_email'))
                    ->required(),

                TextInput::make('footer_phone')
                    ->label(__('fields.settings.footer_phone'))
                    ->required(),

                TextInput::make('footer_address')
                    ->label(__('fields.settings.footer_address'))
                    ->required(),
            ])->columns(3),
        ])
        ->model($this->getThemeSetting())
        ->statePath('data_setting_theme');
}

protected function getFormActions(): array
{
    return [
        Action::make('save')->label('Save data')->submit('save'),
    ];
}

public function save(): void
{
    try {
        $data_tt = $this->settingForm->getState();
        $data_ee = $this->emailForm->getState();
        $data_thth = $this->themeForm->getState();

        $this->handleRecordUpdate($this->getSetting(), $data_tt);
        $this->handleRecordUpdate($this->getEmailSetting(), $data_ee);
        $this->handleRecordUpdate($this->getThemeSetting(), $data_thth);

    } catch (Halt $exception) {
        return;
    }

    Notification::make()
        ->success()
        ->title(__('Successfully data updated'))
        ->send();
}


protected function getSetting()
{
    $setting = Setting::where('id', 1)->first();
    return $setting;
}

protected function getEmailSetting()
{
    $setting_email = SettingEmail::where('id', 1)->first();
    return $setting_email;
}

protected function getThemeSetting()
{
    $setting_theme = SettingTheme::where('id', 1)->first();
    return $setting_theme;
}


protected function fillForms(): void
{
    $data_s = $this->getSetting()->attributesToArray();
    $data_e = $this->getEmailSetting()->attributesToArray();
    $data_t = $this->getThemeSetting()->attributesToArray();

    $this->settingForm->fill($data_s);
    $this->emailForm->fill($data_e);
    $this->themeForm->fill($data_t);
}

protected function handleRecordUpdate(Model $record, array $data): Model
{
    $record->update($data);

    return $record;
}

}

0 likes
4 replies
Fzoltan87's avatar

@Rebwar Yes, I understand that. My question would have been where exactly I should define the tabs within the PHP class, as I have three forms and I want to display them under separate tabs.

They would like to achieve this appearance:

Tabs::make('Tabs') ->tabs([ Tabs\Tab::make('Tab 1') ->schema([ $this->settingForm ]), Tabs\Tab::make('Tab 2') ->schema([ $this->emailForm ]), Tabs\Tab::make('Tab 3') ->schema([ $this->themeForm ]), ])

Rebwar's avatar
Rebwar
Best Answer
Level 32

@Fzoltan87 You can use the Filament Tabs Blade component to add your forms to your custom page Blade file, like in the example below.

1 like
Fzoltan87's avatar

@Rebwar Nice. With a small adjustment, the appearance turned out great. Thank you for your help!

1 like

Please or to participate in this conversation.