tomthestorm

tomthestorm

Live view renders all html in "for" loop not only part of it

Hi I try to understand LiveView . I want to expand and hide HTML after clicking button.
Here code :

use Phoenix.LiveView

  @packs [ 
    %{name: "PACK1", slug: "pack1"} , 
    %{name: "PACK2", slug: "pack2"}
  ]

  def mount(_params, _session , socket) do  
         {:ok, assign(socket,show_pack: false , pack_slug: nil, packs: @packs) }   
  end 
  def handle_event("open_pack", %{"pack_slug" => pack_slug}, socket) do  
    {:noreply, assign(socket,show_pack: true, pack_slug: pack_slug)} 
  end 
  def handle_event("close_pack", %{"pack_slug" => pack_slug} , socket) do  
    {:noreply, assign(socket,show_pack: false, pack_slug: pack_slug) } 
  end 


  def render(assigns) do  
    ~L"""
 <div class="container">
   <%= for pack <- @packs do %> 
     <div class="row"> 
        <div class="column"><b> <%= pack[:name] %> </b> 
           <%= if  pack[:slug] == @pack_slug || @pack_slug == nil do %>  
              <%= if @show_pack == true do %> 
                   <button phx-click="close_pack" phx-value-pack_slug="<%= pack[:slug] %>" > - </button> 
                   <div class="row"> </br>   
                      <div class="column column-offset-10"><b> <%= pack[:name] %> is open </b> </div>          
                    </div> 
              <% else %> 
         
                   <button phx-click="open_pack" phx-value-pack_slug="<%= pack[:slug] %>" > + </button> 
               <% end %> 
           <% end %>   
        </div>
    </div> 
  <% end %>  
</div> 

I want to open and close many packs but keep state if pack is open or closed.
I go through “for” loop to list all packs as initial state (packs are closed) . But when I click (+) button of the first pack , LiveView goes again through whole “for” loop and hide (+) button of the second pack, forever.
I think it should modify only part of code responsible for the first pack but result is different.

Before click (+)


After click (+)

I want to modify part of HTML responsible for certain pack independently, but all code is modified.

Thanks for tip.
Maybe should I use live component ?

Marked As Solved

sfusato

sfusato

Here’s the code for the 1st option:

  @packs [
    %{name: "PACK1", slug: "pack1", show: false},
    %{name: "PACK2", slug: "pack2", show: false},
    %{name: "PACK3", slug: "pack3", show: false},
    %{name: "PACK4", slug: "pack4", show: false}
  ]

  def mount(_params, _session, socket) do
    {:ok, assign(socket, packs: @packs)}
  end

  def render(assigns) do
    ~L"""
     <div class="container">
       <%= for pack <- @packs do %>
         <div class="row">
            <div class="column"><b> <%= pack[:name] %> </b>
              <%= if  pack[:show] do %>
                  <button phx-click="toggle" phx-value-pack_slug="<%= pack[:slug] %>" > - </button>
                  <div class="row"> </br>
                      <div class="column column-offset-10"><b> <%= pack[:name] %> is open </b> </div>
                  </div>
              <% else %>
                    <button phx-click="toggle" phx-value-pack_slug="<%= pack[:slug] %>" > + </button>
              <% end %>
            </div>
        </div>
      <% end %>
    </div>
    """
  end

  def handle_event("toggle", %{"pack_slug" => pack_slug}, socket) do
    socket =
      socket
      |> update(:packs, fn packs ->
        Enum.map(packs, fn
          %{slug: ^pack_slug} = pack -> Map.update!(pack, :show, fn state -> !state end)
          pack -> pack
        end)
      end)

    {:noreply, socket}
  end

Obviously, whenever anything changes inside packs, LiveView will automatically re-render the entire list. An improvement to this implementation would be going the stateful LiveComponent way.

Also Liked

tomthestorm

tomthestorm

Thanks a lot. Now I better understand topic. I try also do this by LiveComponent due to huge list in final implementation of code.

Where Next?

Popular in Questions Top

aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
mgjohns61585
Could someone help me? I’m making my first elixir program, number guessing game. I can’t figure out how to convert the user’s guess from ...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" =&gt; #BSON.ObjectId&lt;58eb1a7a9ad169198c3dXXXX&gt;, "email" =&gt; ...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

Other popular topics Top

senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
985 43487 311
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 31013 112
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement