Collapse Repeaters based on $state or with JS
Hello. I have "Orders". They have many "Items" so I use
Repeater::make
.
I guess you can't use $state
since Collapsible applies to the repeater not to each individual item.
So how can I collapse each item individually based on $state['done']
.
EDIT: Actually I want them to be collapsed (or automatically collapsed onLoad) if done=true
, not collapse them with a button.
In the browser, the "done" filed is a switch, so...
I've tried with JS, but can't figure how to. I was able to get this far using ChatGPT, but I think it does a worse job than I do:
The image below is from my OrdersResouce.php

Solution:Jump to solution
Hey, i looked into Laravel 4.x docs and they added more utilities.
Looking at the https://filamentphp.com/docs/4.x/forms/repeater#collapsing-items table, nothing working for me.
But looking into https://filamentphp.com/docs/4.x/forms/repeater#adding-a-label-to-repeater-items-based-on-their-content table, I noticed "item" param. And it worked:
```php...
17 Replies
Looking at the code I would expect this to work. Can you dump the state in the collapsed callback? Make sure the “done” from the records is actually cast as a Boolean.
The problem, as I expected, is that $state is an array containing ALL
items
. Is not like inside Table
were you access to each row. This is inside Form
, while Editing Order. Maybe I should had state that.
tbh I'm a bit rusted in web development. And new to Laravel ecosystem (i've been using cakephp at work for years)
I'm loading that JS code from a resouce, using this in the AppServiceProvider
I don't know if that's the best way. I actually like to load it only in OrderResources and not App-wide.
Anyway...
Livewire listener works (i don't even know how) but after that, I can't find a good way to diferenciate elements because in the HTML they have no id
attribute. They have the ID inside the cass with an UUID, etcRight, but the view is checking each item’s collapsed state.
Yea because the repeater’s state has UUID’s for each item in the array. But the code should still work
Very well could be a conflict with persisting the collapsed state in the alpine data in local storage too, but I wouldn’t expect that to be a problem since you aren’t explicitly telling it to preserve the collapsed state.
Maybe try
(bool) $state[‘done’]
This plain works.
But as I said (may be wrong), it looks like that $state is an array of several items so I don't know how to access the correct item. If I try
(bool) $state[‘done’]
it throws: Undefined array key "done"
because of that
That's $state
Ah, inject $arguments into the call back then you should be able to target the key in the $state array from the $arguments array.
Hope I’m saying that right.
isCollapased() passes the item back in. So there’s should be a way to get the corresponding key for each item in the callback.
I don't know what I'm doing 😭
ERROR: An attempt was made to evaluate a closure for [Filament\Forms\Components\Repeater], but [$arguments] was unresolvable.
https://github.com/filamentphp/filament/blob/116985735185e2e1380ffa38dcdcb26623f0588e/packages/forms/resources/views/components/repeater/index.blade.php#L101
https://github.com/filamentphp/filament/blob/116985735185e2e1380ffa38dcdcb26623f0588e/packages/forms/src/Components/Concerns/CanBeCollapsed.php#L27
GitHub
filament/packages/forms/src/Components/Concerns/CanBeCollapsed.php ...
A powerful open source UI framework for Laravel • Build and ship admin panels & apps fast with Livewire - filamentphp/filament
GitHub
filament/packages/forms/resources/views/components/repeater/index.b...
A powerful open source UI framework for Laravel • Build and ship admin panels & apps fast with Livewire - filamentphp/filament
Maybe $arguments isn’t right, but the item is passed back, maybe it $data
I might be confusing actions with generic callbacks. Sorry.
Yeah,
$data
is also unresolvable.
I don't understand the magic between Filament, Livewire and Alpine... But it looks like in the "backend" ->collapsed() can't get each database row separately
So yeah, ->collapsed(fn () => rand(0, 1) === 1)
works and some are collapsed in the browser but i don't think it can access each record separatelyExample
See?
->itemLabel()
's $state
is a single record but ->collapsible()
's $state
has all the records. I don't know why. I might open a Feature Request in github I guess?

Since it’s a relationship I wonder if using $record in the callback gives you what your need instead of state.
Repeaters are hard.
Nah, I'm editing an "Order" and it has many "items".
If I use
$record
, I get the Order. If I use $record->items
I get all the items like whem using $state
so i can't access to the current one in the loop.
I've opened a Feature Request (Idea) but since I'm spanish, I don't know if I expresed myself well:
https://github.com/filamentphp/filament/discussions/17269GitHub
Enable access to individual item state in
->collapsed()
callback ...I have Order and it has many associated Items and I use a Repeater to edit or add Items to an Order Currently, when creating a Form, the ->collapsed() callback on a Repeater component only recei...
btw, someone asked this back in 2022 but it seems like only the two of us wanted this functionality (:
Fair enough. Sorry I don’t have a solid answer for you.
No problem. I really apreciate your time 🙂
Just seems like the key should be available with one of the injected parameters.
Item is getting passed back.
Solution
Hey, i looked into Laravel 4.x docs and they added more utilities.
Looking at the https://filamentphp.com/docs/4.x/forms/repeater#collapsing-items table, nothing working for me.
But looking into https://filamentphp.com/docs/4.x/forms/repeater#adding-a-label-to-repeater-items-based-on-their-content table, I noticed "item" param. And it worked:
PS:
I had to remove some incompatible plugins to update to Filament 4 beta to try this.
Then, I discarded all the changes and went back to 3.x just to confirm it also works even while not stated in the 3.x docs.
So this is the current solution so far; using
$item->model->ATTRIBUTE