maximkuzmin

maximkuzmin

Hi!
In my attempt to understand how Phoenix LiveView works, I’m trying to do a somewhat todo-list app, but with a simple twist - each todo item could have an sublist of same-kind todo’s and it goes as far as user needs, similarly to how things are organised in Emacs orgmode.
I store stuff in database like that:

  • Checklists.Checklist - ecto schema that has a jsonb field with entries list, root entity for each checklist, has a list of Checklist.Entry
  • Checklist.Entry - ecto embedded schema that has an optional list of another Checklist.Entry sub-entities

LiveView structure organized in more or less same way:

  • ChecklistLive.Edit - live_view, root one
  • ChecklistLive.EntriesListComponent - live component, receives an entity and renders it’s list of entries using ChecklisterWeb.ChecklistLive.EntryEdit
  • ChecklisterWeb.ChecklistLive.EntryEdit - a form for an Entry and if needed, to list entries sub-entries.

Because of jsonb structure of all entries, when subentity is added/updated, I need to re-save whole checklist and while it’s not optimal, it works for me and way easier than get such tree structure from postgres and/or store it properly with traditional DB structure. Because of it, I update whole checklist on a root level of live view, inside ChecklistLive.Edit process.

It looks and works pretty poorly now, but I achieved adding new entries of checklist and updating them on blur of input. If you don’t go further than first level, it works as expected.
But when I add an sub-entry to any of first level entries, backend part of it works fine - entries are added/updated, whole checklist is saved and when I reload page, I got the structure that I expect.
However, on live view side, not everything is so bright:

  • When I add subentry to existing first level entry, I receive no visual confirmation of it. Subentry looks unsaved until I reload a page. It’s like code that compares old checklist and new checklist doesn’t see this change in sub-entries. If I update/add first level entry, it will work as expected, again.
  • For other fields (timestamps) change happens! So, when I add subentry, I see timestamp of checklist changed, but no subentry added
  • Again, if I reload the page from scratch, added subentries are shown and ready to create their own subentries with similar behaviour

If you’re interested, you can check the code here: GitHub - maximkuzmin/checklister: My approach to build infinitely-nested todo-list (Emacs-orgmode-like) with Phoenix & LiveView · GitHub, however, since I’m not very profound un Ecto/Phoenix/LiveView part of elixir, you can find it not very best-practicey (and maybe this is a real reason, but not sure where to look) :smiley:

Because of the very same reason, my question is - is this behaviour a result of some live-view limitation on nested components or I’ve missed something in documentation?

Showing Posts 1 to 4

cmo

cmo

Have you got ids on the html elements? Maybe the li needs one.

You can certainly nest until your heart is content. I have a SQL query builder that nests and I had some fun issues when I was missing ids.

maximkuzmin

maximkuzmin OP

Hey, thanks for reply!
From reading documentation I understood that only root element of live component need ids and added it, but will play a bit more with you suggestion.

larshei

larshei

I had some funky behaviour sometimes as well, e.g. when deleting an item of a list, a nearby button would disappear as well, or I would see an element twice, or an added element would replace a button etc.

Backend state was always ok, but I think the DOM patch on the frontend got confused.

Solution for me was to give the DOM elements an ID, as @cmo mentioned as well.

So instead of

~H"""
<div :for={user <- @users} class="...">
  <%= user.name %>
</div>
"""

I’d do

~H"""
<div :for={user <- @users} class="..." id={user.id}>
  <%= user.name %>
</div>
"""
sodapopcan

sodapopcan

If you’re using bigint ids, you need to prefix otherwise you’re going to run into conflicting ids:

id={"user_#{user.id}"}

LiveView also use to complain when using bare ints as ids but I just noticed it no longer seems to!

When it comes to nested forms where you can add and remove elements that may not be saved yet, I make ids with the form’s indices:

<inputs_for :let={ff} for={@form[:child]}>
  <input ... id={"child-#{@form.index}-#{ff.index}"}>
</input_for>

This is gives you a predictable id scheme that is shared between persisted and unpersisted records.

— All posts loaded —

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
asweet-confluent
I recently noticed that Elixir’s Logger defaults its primary log level to :debug when no :logger, :level application configuration is pre...
New

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews