Does not LiveView.JS work in a loop?

Hello, I did this function with JS Hook, but I want to know why LiveView.JS does not work in a loop like this:

  defp reset_and_select(js \\ %JS{}, children, id) do
    Enum.map(children, fn %{id: key, data: _data} ->
      js
      |> JS.add_class("hidden", to: "#content-#{key}")
      |> JS.remove_class("border-b", to: "##{key}")
      |> JS.remove_class("border-blue-500", to: "##{key}")
    end)
    |> List.last()
    |> JS.remove_class("hidden", to: "#content-#{id}")
    |> JS.add_class("border-b", to: "##{id}")
    |> JS.add_class("border-blue-500", to: "##{id}")
  end

It just returns the first loop and skips the other.


Update:

I did something like this, but it did not work too.

 def reset_and_select(children, _id) do
    Enum.reduce([:start] ++ children, fn key, acc ->
      if acc == :start do
        %JS{}
      else
        acc
        |> JS.add_class("hidden", to: "#content-#{key}")
      end
    end)
  end

Thank you in advance.

There’s nothing “special” about Phoenix.LiveView.JS. It’s a struct like any other, which you modify and eventually turn into text instructions in your html.

Therefore the Enum.reduce/2 approach should actually work, though it can be a bit simpler by using Enum.reduce/3. Something like this:

defp reset_and_select(js \\ %JS{}, children, id) do
    children
    |> Enum.reduce(js, fn %{id: key, data: _data}, acc ->
      acc
      |> JS.add_class("hidden", to: "#content-#{key}")
      |> JS.remove_class("border-b", to: "##{key}")
      |> JS.remove_class("border-blue-500", to: "##{key}")
    end)
    |> JS.remove_class("hidden", to: "#content-#{id}")
    |> JS.add_class("border-b", to: "##{id}")
    |> JS.add_class("border-blue-500", to: "##{id}")
  end
2 Likes