Using Repeater to save as JSON and display in Table

Hi all, The repeater field is driving me crazy. I use it to save a JSON array in the database but I am not able to display it in a table I have a model called 'Billing' Let's say it has only the fields 'id' and 'validity' This is my code for the Repeater field
Repeater::make('validity')
->schema([
Forms\Components\DatePicker::make('date_from')
->native(false)
->required(),
Forms\Components\TextInput::make('amount')
->required()
->numeric()
->inputMode('decimal')
])
Repeater::make('validity')
->schema([
Forms\Components\DatePicker::make('date_from')
->native(false)
->required(),
Forms\Components\TextInput::make('amount')
->required()
->numeric()
->inputMode('decimal')
])
The entries in the DB look something like in the screenshot. Multiple values for 'validity' are stored like this:
[{"date_from":"2024-02-01","amount":"700"},
{"date_from":"2024-05-13","amount":"750"}]
[{"date_from":"2024-02-01","amount":"700"},
{"date_from":"2024-05-13","amount":"750"}]
So when I render the values in the table, there should be multiple rows for each 'Billing'
I only get it to work if I only display one row like this
Tables\Columns\TextColumn::make('validity.0.date_from')
->date('d.m.Y'),
Tables\Columns\TextColumn::make('validity.0.amount')
->sortable(),
Tables\Columns\TextColumn::make('validity.0.date_from')
->date('d.m.Y'),
Tables\Columns\TextColumn::make('validity.0.amount')
->sortable(),
But this works only for the first element in the array. Can you please help me? How can I use the Repeater field storing the values as JSON (array) and then display all values in the table. Thank you so much
No description
Solution:
Thank you very much. I really wanted to avoid the relationship because json looked so much easier. It very unfortunate that iz does not work with json. I will give it a try with relationship....
Jump to solution
3 Replies
tuto1902
tuto190210mo ago
Since the table is trying to work with simple arrays (no key value pairs) you'll need to format the column state and play around with the values from the validity column, which is an associative array. Here's an example where I flatten the key value pairs into a simple array of strings. Then, I use ->bulleted() to format each array item into a bulleted list.
return $table
->columns([
Tables\Columns\TextColumn::make('validity')
->state(function (Billing $record) {
$result = [];
foreach ($record->validity as $validity) {
$result[] = "date from: {$validity['date_from']}, amount: {$validity['amount']}";
}
return $result;
})
->bulleted()
])
return $table
->columns([
Tables\Columns\TextColumn::make('validity')
->state(function (Billing $record) {
$result = [];
foreach ($record->validity as $validity) {
$result[] = "date from: {$validity['date_from']}, amount: {$validity['amount']}";
}
return $result;
})
->bulleted()
])
No description
tuto1902
tuto190210mo ago
Although, if you need to keep more than one column of information that is related to billings, I would suggest moving away from JSON columns and instead create a validity relationship (HasMany) and then integrate the repeater to work with said relationship. https://filamentphp.com/docs/3.x/forms/fields/repeater#integrating-with-an-eloquent-relationship
Solution
deni_mirza
deni_mirza10mo ago
Thank you very much. I really wanted to avoid the relationship because json looked so much easier. It very unfortunate that iz does not work with json. I will give it a try with relationship. Thank you
Want results from more Discord servers?
Add your server