Nested LiveView Params

260 views
Skip to first unread message

Jonatan Männchen

unread,
Feb 11, 2021, 5:40:49 AM2/11/21
to phoenix-core
Hi,

Problem:

When writing nested live views, the only official way to pass data from parent to child is through session.

This is a bit of a pain since those parameters are only passed on mount and are therefore immutable without re-rendering the whole live view (and therefore losing its internal state). 

Proposal:

I would like to propose that parent / child live views can communicate the same way as the router does with its view. Params can be passed as argument 1 of mount and handle_params will be called if those params change.

Benefits:

State encapsulation & communication are easier if we have all the tools to pass data around. This would for example enable the Surface Library to accept Props to a LiveView the same as it does with LiveComponent.

PR:

If there is some agreement on the topic, I would be happy to provide a PR.

Best,
Jony

Ingmar

unread,
Feb 11, 2021, 5:55:17 AM2/11/21
to phoeni...@googlegroups.com

Op do 11 feb. 2021 om 11:40 schreef Jonatan Männchen <jon...@maennchen.ch>:
--
You received this message because you are subscribed to the Google Groups "phoenix-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to phoenix-core...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/phoenix-core/adf4a79a-3597-4e0d-b196-712ac810827an%40googlegroups.com.

Jonatan Männchen

unread,
Feb 11, 2021, 8:17:41 AM2/11/21
to phoenix-core
Thanks for the link, I didn't find this discussion.

I don't think that this proposal suffers from the same problems for the following reasons:
  1. Instead of copying all assigns, only chosen data is sent to the child component. (Adressing Message Overhead)
  2. As soon as said data changes, the child handle_params will be called to allow the child component to update it's internal state (Adresses Security / out of date)

Jonatan Männchen

unread,
Feb 11, 2021, 8:23:48 AM2/11/21
to phoenix-core
To show what I mean, here's a practical example:

given @max 100
<%= live_render(@socket, MyApp.ThermostatLive, id: "thermostat", params: %{min: 0, max: @max}) %>

This would call mount(%{min: 0, max: 100}, session, socket)

If later the parent live view @max changes to 120, that would call handle_params(%{min: 0, max: 120}, :not_mounted_at_router, socket)

José Valim

unread,
Feb 11, 2021, 8:27:33 AM2/11/21
to phoeni...@googlegroups.com
The problem with params is that they would need to be sent to the client. If they are sent to the client, they need to be encoded (so it becomes like the session) or they are sent as is (but JSON encoded), which means the user can fiddle with them (and you missing that means you are opening yourself up to vulnerabilities).

So I would continue using the session and program the LiveView accordingly to consider some of the params defaults will be session bound.

Jonatan Männchen

unread,
Feb 11, 2021, 8:38:37 AM2/11/21
to phoenix-core
The API is proposed here is based on what I currently know and might be flawed.

Why do they have to be sent tho the client? Can't that be changed?

The idea specifically is:
  • No En-/Decoding
  • A callback that is invoked if those parameters change
I think we should find a way though that does not involve the following:
  1. Setting up a new PubSub to communicate between parent / child
  2. Sending a message from child to parent to register its pid so that updates can be sent
Both of those options are hard for people new to the ecosystem and make it almost impossible to abstract in libraries to that they interoperate nicely.

José Valim

unread,
Feb 11, 2021, 8:48:15 AM2/11/21
to phoeni...@googlegroups.com
The LiveView is a separate process initialized by the client, you have to use a process to communicate it has come to life. That's how it would be implemented in LV - if it was part of LiveView - so luckily there is nothing stopping you from implementing it right now with your own abstractions too. So yeah, I don't see why this has to be part of LV.

Jonatan Männchen

unread,
Feb 11, 2021, 8:53:12 AM2/11/21
to phoenix-core
If I search through Stack Overflow / Elixir Forum etc, I see that various people have this problem. 

For sure this could be solved in "user space", but that stands in the way of having a solution that lets libraries interconnect. Also I would argue that this is a central piece of communication and there should be standardised.

Is there a reason that stops us from implementing this directly in LiveView?

If you do not agree with my argument: Why not? (Even if this never makes it into Live View itself I would be interested to hear your arguments because they might help take an alternate implementation better. as well..)

Ingmar

unread,
Feb 11, 2021, 9:06:50 AM2/11/21
to phoeni...@googlegroups.com
I've been implementing my own bubble up, pass down logic.
It's messy and hard to understand.
I'm not sure José uses a lot of deeply nested components.
He would definately run into these problems.



Op do 11 feb. 2021 om 14:53 schreef Jonatan Männchen <maen...@joshmartin.ch>:
--
You received this message because you are subscribed to the Google Groups "phoenix-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to phoenix-core...@googlegroups.com.

José Valim

unread,
Feb 11, 2021, 10:05:48 AM2/11/21
to phoeni...@googlegroups.com
> For sure this could be solved in "user space", but that stands in the way of having a solution that lets libraries interconnect. Also I would argue that this is a central piece of communication and there should be standardised.

I am not saying it should always be solved in user space: I am saying you should try to tackle it in your project, gather feedback, and once you think you have reached something you believe suits your needs, we can look at another proposal. My point is exactly that the experimentation can happen right now without bottlenecking on the Phoenix team making decisions.

You mentioned Surface a couple times and it is a great example of how you can build new abstractions on top of the ones we have. And I bet some of those will eventually reach upstream.

Reply all
Reply to author
Forward
0 new messages