Same LiveComponent renders in two places?

I wonder if is is feasible to render the same LiveComponent instance in two locations within a LiveView.
The typical case would be a LiveComponent in charge of a state, I would need to display and modify some fields in one HTML location of the LiveView, and the other fields somewhere else (HTML location).
Or, in other words: LiveComponent manages state data= %{a: one, b: two, c: :three}, I need to have a form about a at the top of the LiveView HTML page, a form about b and c at the bottom of the LiveView HTML page.
Of course, the LiveComponent would process the DB access for data as a whole.
That would require calling the LiveComponent twice within the LV, with same id and a way to select a different render function.
Is this crazy thinking ?
Thank you

You cannot have the same LC using the same id multiple times. The whole reason there’s an id is that it uniquely identifies the LC. The also cannot share their state. But it sounds like what you’re looking for could be done without those two things anyways. Have a LC to handle the form – pass in a, b, c individually.

Ok, but I actually need two forms, one for a, one for b&c since those two forms are going to be displayed in separate location of the rendered calling LiveView.
So two forms coded in the same LC but displayed in separate LV locations. Seems impossible.

Why have the two separate forms be handled by one LC though?

I wanted to regroup within the same LiveComponent forms and database code related to the same data.
That way, the forms & its events are processed within the same LC.
How would you do it : define the forms in the parent LV and send the events to the LC state manager ?

The parent LV (or LC) is the only thing containing all parts. If you really want one piece handling everything it should be that parent. Having a single state handling component (process for LV or LC) handle multiple distinct parts of the markup would make things confusing at best imo.

I feel you.
Initially everything was located in the same form and I was happy like a puppy. Then for UI reasons I had to move one of the fields away (HTML wise) from his brothers. And what appeared like a simple graphic change lead to a (possibly) massive change in the code.
My thinking : it would be great to have local state management (LC takes care of changesets, DB…) but spread UI rendering : where things are in the HTML finale page.
But this is the web, not a local app…

You’re free to move business logic to a shared/common place outside of LV/LC implementations. But the LV/LC modules themselves are tightly linked to markup and its hierarchical tree structure.

I’m not arguing here but I’m rather in a learner position.
My business logic is already in a dedicated module.
Then let me rephrase with what I learned from you. : What I’m trying to do is to have the state common to two LiveComponents.
That would require some communication between the module in charge of the common state (a genserver) and the LCs in charge of the markup.

  • Form in charge of “a” located in LC “A”
  • Form in charge of “b” and “c” located in LC “BC”
  • common state for %{a,b,c} in a dedicated Elixir genserver. Genserver performs send_updates to “A” and “BC”
  • “A” and “BC” call genserver API when they need to update state
    Or some pubsub instead of send_update

To me it’s still a bit unclear though why you need a, b, c to be handled together. I generally consider forms to be “low level crud’ish operations”, which might or might not line up with higher level business logic. If they don’t line up you likely want to handle the low level stuff separately from the high level stuff.

I’ll review the code in light of your statement.

I think I had a similar situation where I had state (cart) that lives in the parent LV but is updated from live components (product form LC and cart LC). All cart logic lives in the cart LC and I call the module function needed (cart LC → add product to cart) while handling the form submission in the product form LC.

In the cart LC functions, I broadcast the updated cart data to the parent LV with pubsub and attach_hook which then updates the LV cart state.

Hope this makes sense, tough to explain on mobile.