fbutano

fbutano

List of nested maps not working from liveview

Hello, I have a small phoenix app with just one ecto model called Office with the following schema for parent relationship

defmodule Tree.Arma.Office do
  use Ecto.Schema
  import Ecto.Changeset

  schema "offices" do
    field :name, :string
    belongs_to :parent, Tree.Arma.Office
    has_many :children, Tree.Arma.Office
    timestamps(type: :utc_datetime)
  end

  @doc false
  def changeset(office, attrs) do
    office
    |> cast(attrs, [:id, :name, :parent_id])
    |> validate_required([:name])
  end
end

Inside Arma context I have the following helper function to retrieve a linear list of offices in parent-children relations and works perfectly

def list_descendants(id) do
    base_query =
      Office
      |> where(id: ^id)

    recursive_query =
      Office
      |> join(:inner, [next_descendant], parent in "descendants_list",
        on: next_descendant.parent_id == parent.id
      )

    descendants_query = base_query |> union_all(^recursive_query)

    {"descendants_list", Office}
    |> recursive_ctes(true)
    |> with_cte("descendants_list", as: ^descendants_query)
    |> where([o], o.id != ^id)
    |> Repo.all()
  end

I have also defined the following functions to retrieve a nested map of descendants:

  def nested_tree(parent_id) do
    flat_list = list_descendants(parent_id)
    nester(flat_list, parent_id)
  end

  def nester(flat_list, root_id) do
    lookup = Enum.group_by(flat_list, & &1.parent_id)
    with_children(root_id, lookup)
  end

  defp with_children(root_id, lookup) do
    lookup
    |> Map.get(root_id, [])
    |> Enum.map(&nest_one(&1, lookup))

  end

  defp nest_one(row, lookup) do
    %{row | children: with_children(row.id, lookup)}
  end

So, if we have an Office with id=4 and call nested_tree(4) the function returns a nested map of all the descendants from the Office with id=4.

The problem is that when i call nested_tree from inside an iex -S mix shell all works fine; but when i the function is called from the liveview that shows the details for a sibgle Office, nested_tree() return an empty list. This is the code of the liveview:

defmodule TreeWeb.OfficeLive.Show do
  use TreeWeb, :live_view

  alias Tree.Arma

  @impl true
  def mount(_params, _session, socket) do
    {:ok, socket}
  end

  @impl true
  def handle_params(%{"id" => id}, _, socket) do
    {:noreply,
     socket
     |> assign(:page_title, page_title(socket.assigns.live_action))
     |> assign(:office, Arma.get_office!(id))
     |> assign(:office_tree, Arma.nested_tree(id))
    }
  end

  defp page_title(:show), do: "Show Office"
  defp page_title(:edit), do: "Edit Office"
end

I’ve found that if in the liveview the id of the office is hardcoded when calling nested_tree() it works!
So for example if in the liveview I put:

|> assign(:office_tree, Arma.nested_tree(4)

it works!

I’m really stuck with this, so if anybody can help me I really appreciate!!

Marked As Solved

nTraum

nTraum

Then maybe passing the ID either as a string or as an integer is the reason for the different behaviour you observe.

The params map in the handle_params function always contains string values as far as I know. What happens if you parse to an integer before passing it to your functions?

@impl true
  def handle_params(%{"id" => unsigned_id}, _, socket) do
    id = String.to_integer(unsigned_id)

    {:noreply,
     socket
     |> assign(:page_title, page_title(socket.assigns.live_action))
     |> assign(:office, Arma.get_office!(id))
     |> assign(:office_tree, Arma.nested_tree(id))
    }
  end

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
Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
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
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
dotdotdotPaul
Okay, I’m having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I’m sure I’...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New

Other popular topics Top

WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
TunkShif
This post is an instruction guide to help you setup your Neovim for Elixir development from scratch. It includes general information on h...
274 41539 114
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 43622 214
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 53690 245
New
Lily
In templates/appointment/index.html.eex: <%= for appointment <- @appointments do %> <tr> <td><%= appoi...
New
hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a > b) do {:ok, "a"} end if (a < b) do {:ok, b} end if (a == b) do {:ok, "equa...
New
aesmail
Hello guys, I have finally made it. I created an admin interface for a framework. It’s been on my todo list for years and with the curre...
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
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
AstonJ
We’ve put together this wiki for Phoenix LiveView - please feel free to add any info you feel is worth including. What is Phoenix LiveV...
New

Latest on Elixir Forum

We're in Beta

About us Mission Statement