F
Filament2mo ago
Kyle

Dynamic Fields in a Repeater Table

Hi! I Know everyone is busy so I'll try my best to keep this short. I have a Repeater that is configured to show as a table.
Repeater::make('player_stats')
->table([
TableColumn::make('Data'),
TableColumn::make('Value'),
TableColumn::make('Date')
])
->schema([
Select::make('data')
->options(...)
->required()
->live(),
TextInput::make('value')
->required()
->visible( fn (Get $get) => $get('data') == '1' ),
Select::make('select_value')
->required()
->options( ... )
->visible( fn (Get $get) => $get('data') == '2' ),
DatePicker::make('date')
->required(),
])
Repeater::make('player_stats')
->table([
TableColumn::make('Data'),
TableColumn::make('Value'),
TableColumn::make('Date')
])
->schema([
Select::make('data')
->options(...)
->required()
->live(),
TextInput::make('value')
->required()
->visible( fn (Get $get) => $get('data') == '1' ),
Select::make('select_value')
->required()
->options( ... )
->visible( fn (Get $get) => $get('data') == '2' ),
DatePicker::make('date')
->required(),
])
The problem is that, even if a field is not visible, the field still uses the column, so with only 3 TableColumns, the DatePicker doesn't show. I also tried variations of hide(), visible(), disabled(), and dehydrated() and each field always uses one column of the table. I read that it is possible to use a function instead of an array as a schema, so that the function can compute and return which fields will exist. However, that relies on the fact that the value used to decide which fields are shown exist outside of the schema. In my case, I want the schema to be determined by the value of the data field inside the schema itself. Is there a way to implement this? If not, what is the best approach, while keeping the same table structure? My approach actually works with the Table Repeater component by AWCodes. But I'd rather use the official V4 version of a table repeater if possible. Any recommendations are greatly appreciated! Thank you!!\
31 Replies
LeandroFerreira
LeandroFerreira2mo ago
??
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\Utilities\Get;

...

Repeater::make('player_stats')
->table([
Repeater\TableColumn::make('data'),
Repeater\TableColumn::make('value'),
Repeater\TableColumn::make('date'),
])
->schema([
Select::make('data')
->options([
'1' => 'Option 1',
'2' => 'Option 2',
'3' => 'Option 3',
])
->required()
->live(),
TextInput::make('value')
->visible(fn (Get $get) => $get('data') === '1'),
TextInput::make('str_value')
->visible(fn (Get $get) => $get('data') === '2'),
DatePicker::make('date'),
])
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\Utilities\Get;

...

Repeater::make('player_stats')
->table([
Repeater\TableColumn::make('data'),
Repeater\TableColumn::make('value'),
Repeater\TableColumn::make('date'),
])
->schema([
Select::make('data')
->options([
'1' => 'Option 1',
'2' => 'Option 2',
'3' => 'Option 3',
])
->required()
->live(),
TextInput::make('value')
->visible(fn (Get $get) => $get('data') === '1'),
TextInput::make('str_value')
->visible(fn (Get $get) => $get('data') === '2'),
DatePicker::make('date'),
])
Kyle
KyleOP2mo ago
Yes, that's exactly what I was doing. However, while the TextInput would indeed be hidden based on the closure given to visible, it still takes up one column on the table. And the actual table only has 3 columns. (Sorry, I intentionally did not write the closure with the hope that it would be easier to understand written in English pseudocode instead of PHP. I apologize if it seems that was my problem ^_^; I rewrite those parts in PHP and added more specific settings.)
toeknee
toeknee2mo ago
Where are you getting the dta from? I would probably say get the component and check the first record of the relationship data if it's 1 then show the Column?
Kyle
KyleOP2mo ago
Just to help make things clearer, It's not the hiding of the field that is the problem. It works perfectly. It's that even if a field is hidden (not visible), it still takes up one column on the repeater table. Thanks for asking. The data is from a database record, which is actually a Laravel Relationship. But that's working fine right now. And based on the data field, the column visibility does get changed.
toeknee
toeknee2mo ago
Try (I haven't tested)
Repeater::make('player_stats')
->table([
Repeater\TableColumn::make('data'),
Repeater\TableColumn::make('value')->visible(fn($record) => $record->player_stats->first()?->data === 1),
Repeater\TableColumn::make('date'),
])
->schema([
Select::make('data')
->options([
'1' => 'Option 1',
'2' => 'Option 2',
'3' => 'Option 3',
])
->required()
->live(),
TextInput::make('value')
->visible(fn (Get $get) => $get('data') === '1'),
TextInput::make('str_value')
->visible(fn (Get $get) => $get('data') === '2'),
DatePicker::make('date'),
])
Repeater::make('player_stats')
->table([
Repeater\TableColumn::make('data'),
Repeater\TableColumn::make('value')->visible(fn($record) => $record->player_stats->first()?->data === 1),
Repeater\TableColumn::make('date'),
])
->schema([
Select::make('data')
->options([
'1' => 'Option 1',
'2' => 'Option 2',
'3' => 'Option 3',
])
->required()
->live(),
TextInput::make('value')
->visible(fn (Get $get) => $get('data') === '1'),
TextInput::make('str_value')
->visible(fn (Get $get) => $get('data') === '2'),
DatePicker::make('date'),
])
for example? or else get $livewire in there, and handle it that way.
Kyle
KyleOP2mo ago
I think I could rephrase it like this? I want a table repeater where the schema changes based on the value of the data field. If it is 1, I want to show a TextInput, but if it's 2, I want to show a Select. I hope that makes sense 😅 Thank you very much! Unfortunately, I tried that already and... TableColumns don't have a visible method 🙁
toeknee
toeknee2mo ago
Ohh So then would the player stats be dictated by a type on the event?
Kyle
KyleOP2mo ago
| Data | Value | Date |
| --- | --- | --- |
| 1 | TextInput | 2020-01-01 |
| 1 | TextInput | 2020-01-01 |
| 2 | Select | 2020-02-01 |
| 1 | TextInput | 2020-02-01 |
| Data | Value | Date |
| --- | --- | --- |
| 1 | TextInput | 2020-01-01 |
| 1 | TextInput | 2020-01-01 |
| 2 | Select | 2020-02-01 |
| 1 | TextInput | 2020-02-01 |
I hope this makes sense ^_^
toeknee
toeknee2mo ago
Yes but if you have a mix of data the column always needs to be shown. If you only have 1 type of data for that event, the you need to build it for that type of data, that type of data would tend to be dictated by the event type
Kyle
KyleOP2mo ago
The database itself can accept any value (it's set to accept a single JSON value) so the database column can take a string or an integer. I just want to use a Select for easier input of the value depending on what kind of data is selected. Like, let's say if Data is 1, I need to input the name of the person as Value. So yeah, that needs a TextInput. But if, let's say, the data is 2, I need to choose whether the person is left-handed or right-handed. And a Select works better for that instead of typing "Left-handed" or "Right-handed" (left-handed vs right-handed is not the best example but it's one example.) By the way, thank you very much for your assistance. I apologize if this is a weird case I'm trying to do.
toeknee
toeknee2mo ago
Yes I think I get you now, but the problem you have is, if one row is a select and one is an input you would have a mess of columns then?
Kyle
KyleOP2mo ago
That's true. Which is why I only want to show the best type of input based on the selected Data, and hide the other 🙂 They all go to the same database column. Like, if I'm inputting the height of a person (data == 1), a TextInput (set to numeric) would be the best. But if I'm inputting the blood type of a person (data == 2), a Select would work way better than manually keying the blood type with a keyboard. In any case, the type of data goes to the database "data" column, and the value (height, or blood type) would go to the database "value" column (which can take string or integer no problem). Again, apologies if I'm asking for something impossible. Thank you very much for being so patient.
toeknee
toeknee2mo ago
I think I get you, but then you always have 3 columns regardless of the type?
Kyle
KyleOP2mo ago
Hmm, that was my initial thought--to have 4 fields, then just hide the field that isn't needed... Select (choose the kind of data) TextInput or Select (depending on the kind of data) DateInput (timestamp of data) But I guess for a repeater table, ideally, the unneeded field shouldn't be in the array at all. Because if a field is in the array, even if it's hidden, it takes up one column in the repeater table.
toeknee
toeknee2mo ago
Ahh now I see what you are saying, a blank column is being added regardless?
Kyle
KyleOP2mo ago
Having it in the schema array but hidden just results in something like this.
No description
toeknee
toeknee2mo ago
Do you have 4 columns set there?
Kyle
KyleOP2mo ago
And that is when I have 4 TableColumns. If I only use 3 TableColumns, then the date field disappears completely.
toeknee
toeknee2mo ago
Ahh I got you, that's a limitation of the repeater class then, interesting.
Kyle
KyleOP2mo ago
Yes! I tried both 4 and 3 columns, but... I don't know how to make it work 🙁 I'm sorry.
toeknee
toeknee2mo ago
It must be counting arrays
Kyle
KyleOP2mo ago
Actually, like in my original message, it works in AWCodes custom TableRepeater field. But personally, since repeater tables are now implemented in Filament V4, I'd rather use V4's official implementation. If possible, of course.
toeknee
toeknee2mo ago
Yeah I get that, I think we should be checking the values before assuming they are all renderable. Raise a Github Issue and reproduction repo please.
Kyle
KyleOP2mo ago
Oh, wow! I see... Thank you very much for your consideration! I'll make a reproducible GitHub repo and submit an issue. Thank you very much for your attention regarding this problem. I apologize that my original message was quite confusing to understand.
Kyle
KyleOP2mo ago
@toeknee I did my best and created a pull request instead of an issue. https://github.com/filamentphp/filament/pull/17406
GitHub
Allow user to configure whether hidden fields in Repeater table occ...
Description There are times when using a Repeater configured to show as a table, a field gets hidden. Before, such hidden fields still occupy a column on the table even when it is not displayed. Th...
toeknee
toeknee2mo ago
Great stuff!
LeandroFerreira
LeandroFerreira2mo ago
maybe this
GitHub
Add Schema component support to Table repeater by leandrocfe · Pul...
Description PR #17406 shows that we can't use a TableRepeater with a dynamic field. With this changes, TableRepeater supports Schema components, allowing us to use a Group component to crea...
Kyle
KyleOP2mo ago
Yes!! Thank you, @Leandro Ferreira and @toeknee ! Patiently waiting for official release.
toeknee
toeknee2mo ago
REally neat approach, will be interesting to see how that works.
Kyle
KyleOP2mo ago
Really makes a difference when the dev is 100% familiar with the codebase 😭 To be honest, I didn't know about the Group component so I didn't even think of trying it 😅
toeknee
toeknee2mo ago
Yeah totally get that

Did you find this page helpful?