How to get items' indices when using streams?

Hi everyone!

I have a list of items that I display in Phoenix LiveView using streams.

Currently, I am working on the “Clone” feature. any item can be cloned and the new (cloned) item is supposed to appear right below the item being cloned.

I want to use stream_insert(..., at: position) but for this to work, I need to know the relative position of every item on the list.

I tried a few variations of the following in my view:

:for={ {{dom_id, entry}, position} <- Enum.with_index(@streams.entries) }

but I get the following error:

streams can only be consumed directly by a for comprehension. If you are attempting to consume the stream ahead of time, such as with Enum.with_index(@streams.entries), you need to place the relevant information within the stream items instead.

I have no idea how to proceed in a way that would be idiomatic. I am sure I can hack my way out of this - but there’s got to be “the right way” to do it…

Thanks in advance!

The only way I have found to do this, is to “enrich” your item with it’s index.
You cannot just use Enum.with_index/1 because stream requires your item to be a Map with an :id.

I must be missing something, but would not Stream.with_index/2 do?

We are talking about a Phoenix.LiveView stream, not Elixir.Stream.
Confusing that they chose the same term.

1 Like

Thanks for clarifying!

I can’t “enrich” the item because of sorting and filtering options in my view. The items may be displayed in a different order every time.

I will have to live with the cloned items appearing at the bottom of the view.

All the best,
Michal

But I was thinking… I’ll try accessing the items in my stream in handle_event, finding the right item and figuring out its index. Maybe it will work.

Cheers!