Discount week! Until September 16th, 50% off Yearly/Lifetime membership and FilaCheck Pro — applied automatically at checkout, no coupon needed!

Filament Complex Product Form: Tabs and v5.8 Defer Schema

Filament 4/5

Filament form for products that uses Tabs with Variants and Related products, with pretty complex schema and optimized with the new Filament 5.8 feature of deferred schema loading.

Untitled design (49)

Get the Source Code:

Only This Example

$9

One-time payment

Full source code for Filament Complex Product Form: Tabs and v5.8 Defer Schema
Downloadable ZIP file with the source code
Lifetime access to this example
GitHub Sign in with GitHub to buy

Sign in first, then complete your $9 checkout.

Best value — all 176 examples

FilamentExamples Membership

$99 /year
or
$199 lifetime
Access to code of all 176 examples
Future new examples and updates included
FilaCheck Pro package licence included
MCP server included
View membership plans

30-day money-back guarantee

How it works

This project demonstrates Filament's deferred schema loading, which lets any part of a form skip rendering until it actually becomes visible. It builds a realistic e-commerce product editor — eight tabs, a fifty-item variants repeater, and selects backed by thousands of records — and then defers almost all of it.

The key idea is that a component's schema() can accept a Schema object instead of a plain array, and that object can be marked with ->deferLoading(). Filament then renders a lightweight placeholder in its place. When the placeholder enters the viewport, an intersection observer triggers a Livewire partial render of just that one schema. Tabs the user never opens are never rendered at all — not on the client, and not on the server.

On the seeded showcase product, this takes the edit page from 2,869 KB of HTML down to 737 KB without changing a single field, a validation rule, or a line of business logic.

The repository contains the complete Laravel + Filament project to demonstrate the functionality, including a seeded catalogue of 5,000 products, an environment toggle to switch deferring on and off for comparison, and tests covering both states.

The Filament project is in the app/Filament folder.

Feel free to pick the parts that you actually need in your projects.


How to install

  • Clone the repository with git clone
  • Copy the .env.example file to .env and edit database credentials there (the default is SQLite)
  • Run composer install
  • Run php artisan key:generate
  • Run php artisan storage:link
  • Run php artisan migrate --seed
  • That's it: launch the URL /admin and log in with credentials [email protected] and password

The seeder prints the URL of the showcase product when it finishes — the one with fifty variants that makes the difference obvious.


How It Works

The application is organized around a single Filament resource. The form is split into tabs, and each tab hands Filament a Schema object that knows whether it should render immediately or wait until the user actually looks at it.

1. ProductForm — Tabs That Decide What Renders

The form is one Tabs component holding eight tabs, each built by its own private method. Splitting them this way keeps the deferring decision visible per tab rather than buried in one long array.

app/Filament/Resources/Products/Schemas/ProductForm.php

public static function configure(Schema $schema): Schema
{
return $schema
->components([
Tabs::make('Product')
->persistTabInQueryString()
->columnSpanFull()
->tabs([
self::generalTab(),
self::pricingTab(),
self::inventoryTab(),
self::variantsTab(),
self::mediaTab(),
self::shippingTab(),
self::seoTab(),
self::relatedProductsTab(),
]),
]);
}

The General tab is deliberately left undeferred. It renders on every page load, which gives you a baseline to compare against — and reflects real practice, where the fields people edit most often are worth rendering up front.

The key points:

  • Every tab except General passes a Schema object rather than an array, which is what makes deferring possible in the first place
  • Deferring is a per-schema decision, not a global setting, so the fields you edit constantly stay instant while the rare ones stay out of the way
  • persistTabInQueryString() keeps the active tab in the URL, and on reload Filament restores that tab — which also loads its schema
  • Tabs are concealed with display: none rather than removed, so an inactive tab's deferred schema stays unloaded until the tab is actually selected

2. deferLoading() — The Core Pattern

The Inventory tab is the clearest example of the pattern. The whole tab body is...

The FULL tutorial is available after the purchase: in the Readme file of the official repository you would get invited to.