F
Filament4mo ago
Ryuuji

How can i create a custom field that contains other fields?

I want to create a custom field that can contain other Filament Fields (defined on my custom field, not through the schema outside) but i cant seem to make it work, if i try to directly render a TextInput inside of my custom field I get the error of Typed property Filament\Forms\Components\Component::$container must not be accessed before initialization
<div>
@php
// Here I really bring the item from the php side.
$item = \Filament\Forms\Components\TextInput::make('test')
@endphp
{{$item}}
</div>
<div>
@php
// Here I really bring the item from the php side.
$item = \Filament\Forms\Components\TextInput::make('test')
@endphp
{{$item}}
</div>
So I guess there is some setup i need to make to support this, but my only reference is the Repeater component that also contains fields but is too complex and I haven't been able to follow the logic
6 Replies
igorclauss
igorclauss4mo ago
Have you tried the Builder Component? It's a form component where you can use ->blocks() method to define dynamic component blocks
Ryuuji
RyuujiOP4mo ago
not really, i need to build a custom component that has the structure of the picture, where the blue boxes are number inputs and the yellow sums the values of each item the idea for the project i'm doing is that every field is selfcontained in his logic
No description
igorclauss
igorclauss4mo ago
Are the list of items variable in it's length?
Ryuuji
RyuujiOP4mo ago
its predefined
igorclauss
igorclauss4mo ago
I would probably use a builder with a block with a repeater with three textInputs and three readonly textInputs for the sums. Then heavily rely on afterStateUpdated() and update the sums.
Ryuuji
RyuujiOP4mo ago
not the solution i wanted hahah buuut I think I'm onto something, the data components appear to flow from the childComponents array of the field so I need my fields stored there to work correctly. With that i can build my component like this
class BudgetByItem extends Field
{

protected string $view = 'forms::components.inputs.budget-by-item';

protected function setUp(): void
{
parent::setUp();
$this->columnSpanFull();
$this->schema([
TextInput::make('test1'),
TextInput::make('test2')
]);
}

public function getFields()
{
$components = parent::getChildComponents();
$keyed = collect($components)->keyBy(function ($item) {
return $item->statePath;
});

return $keyed->toArray();
}
}
class BudgetByItem extends Field
{

protected string $view = 'forms::components.inputs.budget-by-item';

protected function setUp(): void
{
parent::setUp();
$this->columnSpanFull();
$this->schema([
TextInput::make('test1'),
TextInput::make('test2')
]);
}

public function getFields()
{
$components = parent::getChildComponents();
$keyed = collect($components)->keyBy(function ($item) {
return $item->statePath;
});

return $keyed->toArray();
}
}
and the view can access a known field given its state path
@php
$fields = $getFields();
@endphp
<div>
<div class="bg-red-500 p-4">
{{$fields['test1']}}
</div>

<div class="bg-blue-800 p-4">
{{$fields['test2']}}
</div>

</div>
@php
$fields = $getFields();
@endphp
<div>
<div class="bg-red-500 p-4">
{{$fields['test1']}}
</div>

<div class="bg-blue-800 p-4">
{{$fields['test2']}}
</div>

</div>
though i still haven't found where is the $container injected if i can find it there could be a simpler way of doing this hahaha

Did you find this page helpful?