How to handle records of different "type" and different fields depending on the type?
Hey! I have a simple model called "Visual". It has the fields
name
(string), type
(enum) and settings
(json). In a CMS the record should represent any type of visual objects like an image, a slider, a video, a chart, a pdf, whatever.. Each type has completely different fields which should be stored into settings
column. So for example image just have a FileUpload. A slider has multiple FileUploads, a chart may have just a Codefield to insert a iframe-code or whatever...
How can I use different fields depending on the selected type in the Select for "type"?
To may make it little bit more challenging (for me): For each of those visual types we have packages to only install only the types we need for the website. The packages register them self in a VisualTypeRegistry. A VisualType object has a getKey() ``getLabel()
and getSchema()
function. Building the type Select works well depending on the key and the label. But now I don't know how to tell filament to use the getSchema() for the selected type.12 Replies
I would use a Builder field for this
it uses 1 json object instead of multiple visual models
But at the end if have may 20 images, 5 sliders and 7 youtube videos. So I would need 32 visual records
or do you mean adding a builder field with maxItems(1) and minItems(1) and each visual type will represent one block?
a block is Image, Slider, YoutubeVideo
your JSON contains an array of x items of these types
1 record need to represent 1 visual
so I could solve this problem with a builder with using min/max Items 1 but feels like a workaround
does it need to though?
im just talking about the UI here really, the builder was made for this
The problem is, that I want to re-use for example one visual on may 5 different pages. They should be re-usable.
I love the builder. The whole CMS and the building of the pages itself depend on the builder.
so you were planning on using a repeater or something to handle the different reusable blocks?
i understand what you mean by maxItems now
you could use a Select and then a Grid/Group/Fieldset or something to dynamically generate field based on that
on the Select, you need
->reactive()->afterStateUpdated(fn ($component) => $component->getContainer()->getComponents()[1]->getChildComponentContainer()->fill())
to ensure that the group is reinitialised when it changes (assuming the Group is the second field in the array, you might need to change 1 to a different index)@Dan Harrin I think thats definitely the direction I need to go.
Unfortunately Group complains about the Closure in the make(). I'm doing something wrong here?
return $form
->schema(
[
Forms\Components\TextInput::make('name')
->label('Name')
->required(),
Forms\Components\Select::make('type')
->options($visualTypeRegistry->getOptions() )
->reactive()
->afterStateUpdated(
fn ($component) => $component->getContainer()->getComponents()[2]->getChildComponentContainer()->fill()
),
Forms\Components\Grid::make(function ($get) {
$select = $get('type');
return [ Forms\Components\TextInput::make('a field for '.$select) ];
})->statePath('settings'),
]
);
Try
Group::make()->schema([
awesome
meci π
For editing I wouldn't show the option to change the type at all. But for creation it would be pretty nice to put those fields into a two steps wizard. First for name and type. Second for the settings.
Is it possible to adjust this code that it triggers the first components on the second wizard page?
$component->getContainer()->getComponents()[2]->getChildComponentContainer()->fill()