Hi
This is my first post here.
I have a list of items that each have a date field.
When redndering the list, its sorted by this date field,
and now I would like to add a small header everytime the date changes.
Example:
14th March 2024
Item 1
Item 2
Item 3
13th March 2024
Item 4
Item 5
11th March 2024
Item 6
Current loop:
<div id="events" phx-update="stream" class="space-y-4">
<%= for {id, event} <- @streams.events do %>
## Render event
<% end %>
</div>
My first approach coming from other languages would have been to assign a small variable like
last_date_seen, and in the for loop check if last_date_seen is the same or not as the current date.
But from what I learned this is not advisable, because it will break change tracking.
Using intersperse seems also not feasible, since it would put a header between each item, even if they have the same date.
The Enum.group_by call basically says “group items by the date field and only give me their name field after”.
You can flatten the resulting map to a list exactly the way you need it in the UI. I say give it a try and if you still can’t, I (or somebody else) can give you the next hint.
@streams.events
|> Map.values()
|> Enum.sort_by(& &1.date)
|> Enum.chunk_by(& &1.date)
|> Enum.map(fn chunk ->
# here, chunk is a list of events that all have the same `date` value
# you can get that date from hd(chunk).date
end)
Can you hide all that Enum mapping/chunking/grouping in a function, passing in the stream, without breaking change tracking? Or does it have to happen in the template to keep change tracking happy?