streamelixirliveview

How to update assigns inside phx-update="stream" block of code in LiveView


I have a list of notes to show using LiveView stream, and I want to use an assign called online_users_map continuously updated by Phoenix Presence, in order to show which note's author is currently online . In the sample code below, I noticed the first inspect prints the updated map as users join or leave, but the second inspect remains %{} which leads me to think assigns in a stream phx-update block of code is static. Is that correct? If so, how do I make the dynamically changing assign value available in the stream block?

   <div>
    <%= inspect(@online_users_map) %>   <<< This prints correctly
      <ul
        phx-update="stream"
        phx-viewport-top={@page_no > 1 && "prev-page"}
        phx-viewport-bottom={!@end_of_timeline? && "next-page"}
        phx-page-loading
        id="searched_notess"
        class={[
          if(@end_of_timeline?, do: "pb-4", else: "pb-[calc(200vh)]"),
          if(@page_no == 1, do: "pt-4", else: "pt-[calc(200vh)]")
        ]}
      >

      <%= inspect(@online_users_map) %>  <<< This only prints %{}

        <li
          :for={{dom_id, note} <- @streams.searched_notes}
          class="pb-2 sm:pb-2 mt-2 flex flex-row "
          id={dom_id}
        >

Solution

  • phx-update is used to prevent any changes in the LiveView. When setting it to phx-update="stream" the HTML is rendered based on the streams content, but then the data, e.g. @streams.searched_notes is removed from the socket assigns (see LiveView stream docs). So I would agree, that the HTML rendered inside the stream-block is "static" and you can change only it by using stream_insert and stream_delete on server side.

    Therefore, I believe, the only way to access the @online_users_map assigns would be to integrate the data into the @stream.searched_notes. Probably as another field inside a note element, such as author_online: <true | false>. Of course this would only work if you plan to display the information for each note, but this is not described in the question.