F
Filament10mo ago
ebermor

repeater

Is there a way to add items to the repeater dynamically without having to click the add button?
11 Replies
Positiverain
Positiverain10mo ago
I have the same question, so adding this: Is it possible to add more items by selecting an item from a select input? for example item1 of the repeater is a select, by selecting a value it adds another item, item2 to the repeater, which has the same select input. Am gonna use it for a model that has a parent and some children of same model type, self referencing models.
Vp
Vp10mo ago
could be, not sure tho..
cheesegrits
cheesegrits10mo ago
A Repeater is just a form component, so you can $get and $set the state, which is an array of arrays, being the repeat instances, with their field names and values. So yes, you can add and remove repeats in response to inputs elsewhere on the form using afterStateUpdated() with a closure.
Positiverain
Positiverain10mo ago
Forms\Components\Repeater::make('repeater')
->schema([
Forms\Components\Select::make('test')
->afterStateUpdated(function ($set, $state) {

})
])
Forms\Components\Repeater::make('repeater')
->schema([
Forms\Components\Select::make('test')
->afterStateUpdated(function ($set, $state) {

})
])
How do I use the afterStateUpdated to change the ->defaultItems() of the repeater in this situation?
jouni.i
jouni.i10mo ago
I think repeator is the issue, I use repeator with ->relationship('relation name'), ->default([array of default values]) doesn't work if relationship is empty and ->defaultItems (number of default items) also doesn't work.. but if the relation is not empty, the values will be displayed correctly in the format although I'm not sure if this problem is related to this issue, but I thought I'd let you know
ebermor
ebermor10mo ago
I have a relationship and for each item I need to create an item in the repeater and assign the values ​​to the fields dynamically without the user having to click on add and enter the data manually
cheesegrits
cheesegrits10mo ago
@Positive could you start your own thread, please? Your use case seems to be different, and it just gets confusing with two different questions going on in the same thread. So is your repeater on the relationship itself, or a separate, non-relationship repeater?
ebermor
ebermor10mo ago
Is in a Relationship. For example, a recipe has many ingredients. These ingredients are already pre-registered in the ingredients table. Whenever I create a new recipe, I need to take these pre-registered ingredients and assign them dynamically in the repeater to later save them in recipe_ingredient. User does not need to click add button of repeater
cheesegrits
cheesegrits8mo ago
Yes, you do need to generate the UUID. Here's an example from one of my apps. I'm not doing it on an action, I'm doing it on an afterStateUpdated() on a Select, where the thing they select dictates how many instances of a Repeater I need. The relevant fragment is ...
// $role->slug is the name of the Repeater
$repeats = $get($role->slug);
// get the number of repeats we need
$number = AircraftHelper::getAircraftRoleCount($aircraft->id, $role->slug);

// if the new number is less than existing, chop off the excess
if ($number < count($repeats)) {
array_splice(
$repeats,
$number,
count($repeats) - $number,
);
}

// add additional repeat instances if new number is greater than existing instances
if ($number > count($repeats)) {
for ($x = count($repeats); $x < $number; $x++) {
$repeats[(string) Str::uuid()] = [
'unstaffed' => false,
'personnel_role_id' => $role->id,
'personnel_id' => null,
'duty_start' => DailyLogHelper::getStandardDutyStart($aircraft->id),
'duty_stop' => DailyLogHelper::getStandardDutyStop($aircraft->id),
];
}
}

$set($role->slug, $repeats);
// $role->slug is the name of the Repeater
$repeats = $get($role->slug);
// get the number of repeats we need
$number = AircraftHelper::getAircraftRoleCount($aircraft->id, $role->slug);

// if the new number is less than existing, chop off the excess
if ($number < count($repeats)) {
array_splice(
$repeats,
$number,
count($repeats) - $number,
);
}

// add additional repeat instances if new number is greater than existing instances
if ($number > count($repeats)) {
for ($x = count($repeats); $x < $number; $x++) {
$repeats[(string) Str::uuid()] = [
'unstaffed' => false,
'personnel_role_id' => $role->id,
'personnel_id' => null,
'duty_start' => DailyLogHelper::getStandardDutyStart($aircraft->id),
'duty_stop' => DailyLogHelper::getStandardDutyStop($aircraft->id),
];
}
}

$set($role->slug, $repeats);
Note that I'm not prepending the UUID with record-. I'm pretty sure Filament only expects that prefix for existing data, where it's record-<key>. A new instance would just be a UUID. And yes, I'm individually setting up each field in the repeat.