If you want a true SPA style liveview, you can do this, but you just do it differently than a multi page style liveview. You have a single liveview, and then use the action to switch out components on the page to simulate changing pages.
Hi @pillaiindu,
Unfortunately I had a stroke more than a year ago. From this time, I lost all of my languages (so English is not very good, sorry!), so I can’t tell you when I will take a look at the Live View (of Drab). Sorry!
I did that some time ago. I had problems with adding / removing live views, because there was no way to tell the LiveView JS that the HTML changed after a Turbolinks transition. Only the connect()
call or DOMContentLoaded
event seem to trigger the right logic. So I had to reinitialize a LiveView socket on every page transition, which was really slow and negated the benefits of Turbolinks.
It might not be super hard to fix that use case by having a public API to tell LiveView to reconcile its state with the HTML page.
To clarify, both use cases are possible as long as you fully migrate to LiveView. My reply was in the context of a mixed scenario, when live and non-live views are used. This seems to be what was asked but I may have misunderstood it. I have also changed my previous response to avoid confusion.
Thanks from clarifying. Yeah, it seems it could be done by exporting a proper API.
Yeah, this is what I’m doing in my app. Using a mix of live_redirect
and live_patch
depending on what LV I’m on. But, if this is the route you take, then you can’t pin things like Turbolinks can with its permanence feature right?
Or perhaps you could with using live_patch
for every page transition in the whole site, but that’s going to make things wildly complicated if you have to manually be responsible for resetting the socket’s state depending on what LV you’re on (instead of depending on mount
if you used live_redirect
). That would also mean your whole app would be a single LV right? Not just a series of page transitions using live_redirect
with multiple LVs.
This is the problem I was battling when I wanted to keep an iframe from being reset between page views. The only way I could do this was by having 1 LV be responsible for rendering many different “pages” while using live_patch
to transition between them. Things got so complex so quickly that I ended up backing out of using LV entirely. And that was only trying to display a few pages worth of content, not the entire app.
And as I pointed out on IRC, I am doing exactly that quite successfully. I realize that there are some challenges there, in that I made mine part of the layout to make that work, but the live views do control assigns for the layout. I understand you ran into difficulties, but assertions that it is impossible are unfounded.
I never said it was impossible. But realistically speaking, if you want to pin something to a specific set of pages, you’re going to run into the same issue I had where you have to use 1 LV and live_patch
between pages. Otherwise LV will start swapping it around in the DOM and cause all sorts of issues.
Why is my experience not realistic? We have customers that carry on intercom conversations with us over different pages without interruption daily. Again, I recognize that your situation didn’t work out. However the argument that you’re making over your forum posts is essentially: “An iframe across multiple pages didn’t work for me, and therefore is impractical. A single live view managing multiple psuedo-pages got too complicated, and components are too hard, so that can’t work either.”
I’m not entirely sure what conclusion you’re aiming for with those, although the impression you’re creating at least is “LV is worse than turbolinks”. Both this conclusion and the aspects of the argument leading up to it however are, amongst other things, not the right spirit to be bringing to this discussion. LV is still very new, let’s come at this from the perspective of “How can we make this work better?”, with an ethos of constructive, positive feedback.
You can by using two LiveViews. One will be rendered in the root.html.eex by calling live_render explicitly. The other is your regular LiveView which still will work just fine, with live_patch, live_redirect, whatever. Whenever you don’t want to ever change, put in your root layout.
I’m really sorry to hear that!
Thank you for your contributions to the community!
Get well soon!
When you have multiple live views on a page, they’re guaranteed to run in the same node right? Since they’re going to be using the same underlying transport pid.
This one looks like the best solution.
If someone has already tried this route, please comment!
Did you use data-turbolinks-permanent
attribute on the element you wanted to persist from page to page?
If you use live_patch
between 2 completely different LVs, how does that work when it comes to mount and handle_params? For example, let’s say you want things loaded in both LVs but you only want to fetch them once (without doing any type of caching, since as we all know caching is hard to keep track of).
I thought the difference between patch and redirect was that patch wouldn’t re-run mount. That makes sense if you’re dealing with 1 LV, but with 2, that throws off my whole mental model of how things work.
<%= live_render(@conn, MyChatLive, ...) %>
in your root layout would give you an isolated LV that survives live navigation of the main LV from the live
route. We replace everything inside the main LV on navigation, so anything outside of it won’t be touched.
Thank you Chris for the comment!
In this case, do we need to create the whole app as a LiveView app?
We can discuss a bunch of different scenarios - and we have done so - but unless you effectively go and try things out, it is unlikely we will come up with all the answers that you need.
Now, that mix phx.new --live
is available, you can even build something minimal, share the code with everyone, and talk about what worked and what did not. Code speaks more than words in these cases.
Not to derail the conversation (I did use LV + Turbolinks, but not for the same use case), but my problem was with elements that don’t persist between pages. LiveView won’t pick up newly added live views unless you recreate the socket. It’s not a problem if you use LV exclusively, without Turbolinks.
I am considering creating a single LiveView as you stated, but am I understanding correctly in that socket assigns are available in the layout? If so, I hadn’t realized that and it would make the single LiveView option much easier to reason.
That is correct, if you create your layouts according to this: https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.html#module-live-layouts