Nice to meet you, we're Backstage
Hi! We are a web development agency from Nijmegen in the Netherlands and we use Laravel for everything: advanced websites with a lot of bells and whitles and large web applications.
This package aims to help you add dynamic, configurable fields to your Filament resources with minimal setup. It comes with all standard Filament Form fields out of the box, while providing a flexible architecture for creating custom fields. By giving users the ability to define and customize form fields through an intuitive interface, this package essentially enables user-driven form building within your Filament admin panel.
- π― Easy Integration: Seamlessly integrates with your Filament resources
- π§ Configurable Fields: Add and manage custom fields for your models
- π¨ Built-in Field Types: Includes common Filament form fields like:
- Text
- Textarea
- Rich Text Editor
- Select
- Checkbox
- Checkbox List
- Key-Value
- Radio
- Toggle
- Color Picker
- DateTime
- Tags
- β¨ Extensible: Create your own custom field types
- π Data Mutation: Hooks to modify field data before filling forms or saving
- π’ Multi-tenant Support: Built-in support for multi-tenant applications
This package is perfect for scenarios where you need to:
- Add dynamic custom fields to your models
- Allow users to configure form fields through the admin panel
- Build flexible content management systems
- Create customizable settings pages
You can install the package via composer:
composer require backstage/fields
You should publish the config file first with:
php artisan vendor:publish --tag="fields-config"
This will create a fields.php
file in your config
directory. Make sure to fill in the tenant relationship and the tenant model (if you're using multi-tenancy). When running the migrations, the fields table will be created with the correct tenant relationship.
The content of the fields.php
file is as follows:
<?php
return [
'tenancy' => [
'is_tenant_aware' => true,
'relationship' => 'tenant',
// 'model' => \App\Models\Tenant::class,
// The key (id, ulid, uuid) to use for the tenant relationship
'key' => 'id',
],
'custom_fields' => [
// App\Fields\CustomField::class,
],
// When populating the select field, this will be used to build the relationship options.
'selectable_resources' => [
// App\Filament\Resources\ContentResource::class,
],
];
You can publish and run the migrations with:
php artisan vendor:publish --tag="fields-migrations"
php artisan migrate
When one of your models has configurable fields, you need to add the HasFields
trait to your model.
The trait will add a fields
relation to your model, and define the valueColumn
property. This is the column that will be used to store the field values. Because the values are stored as json, you should cast this column to an array.
If you want to use any other column name for the values, you can set the valueColumn
property in your model.
use Illuminate\Database\Eloquent\Model;
use Backstage\Fields\Concerns\HasFields;
class Content extends Model
{
use HasFields;
// ...
}
To add configurable fields to your related models, we provide a FieldsRelationManager
that you can add to your resource.
use Backstage\Fields\Filament\RelationManagers\FieldsRelationManager;
class ContentResource extends Resource
{
protected static ?string $model = Content::class;
// ...
public static function getRelations(): array
{
return [
FieldsRelationManager::class,
];
}
}
To make a resource page configurable, you need to add the CanMapDynamicFields
trait to your page. For this example, we'll make a EditContent
page configurable.
<?php
namespace Backstage\Resources\ContentResource\Pages;
use Filament\Forms\Components\Grid;
use Filament\Forms\Components\Tabs;
use Filament\Forms\Components\Tabs\Tab;
use Filament\Forms\Form;
use Filament\Resources\Pages\EditRecord;
use Backstage\Fields\Concerns\CanMapDynamicFields;
class EditContent extends EditRecord
{
protected static string $resource = ContentResource::class;
use CanMapDynamicFields;
public function form(Form $form): Form
{
return $form
->schema($this->resolveFormFields());
}
public function mutateFormDataBeforeSave(array $data): array
{
$this->mutateBeforeSave($data);
return $data;
}
}
To conditionally show the fields relation manager, you can override the canViewForRecord
method in your relation manager.
<?php
namespace App\Filament\Resources\ContentResource\RelationManagers;
use Illuminate\Database\Eloquent\Model;
use Backstage\Fields\Filament\RelationManagers\FieldsRelationManager as RelationManagersFieldsRelationManager;
class FieldsRelationManager extends RelationManagersFieldsRelationManager
{
public static function canViewForRecord(Model $ownerRecord, string $pageClass): bool
{
parent::canViewForRecord($ownerRecord, $pageClass);
// Add your own logic here
return ! $ownerRecord->hasPdf();
}
}
To make a custom page configurable, you need to add the CanMapDynamicFields
trait to your page and set the record
property on the page. This way the fields will be populated with the fields of the record.
class YourCustomPage extends Page
{
use CanMapDynamicFields;
public $record;
public function mount()
{
$this->record = YourModel::find($this->recordId);
}
}
When using select fields, you may want to populate the options with relations in your application. To be able to do this, you need to add the resources to the fields.selectable_resources
config array. We then get the options from the table that belongs to the resource and model.
return [
// ...
'selectable_resources' => [
App\Filament\Resources\ContentResource::class,
]
];
...
To register your own fields, you can add them to the fields.fields
config array.
'custom_fields' => [
App\Fields\CustomField::class,
],
composer test
Please see CHANGELOG for more information on what has changed recently.
Please see CONTRIBUTING for details.
Please review our security policy on how to report security vulnerabilities.
The MIT License (MIT). Please see License File for more information.