-
Notifications
You must be signed in to change notification settings - Fork 893
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The navigation/client-state story #136
Comments
An update: unfortunately the URL approach does not work with nested live views. We will probably have to restrict this to somehow. EDIT: for now, we can limit |
If we change URL in the browser using JavaScript/LiveView, we probably also want to handle back and forward browser buttons, i.e. implement the reverse: changing URL on the client would trigger switching between tabs. Another thing a programmer has to take care here is making sure that the application renders the same page on given path of what he or she just set from LiveView, so that when user reloads the page, they would see the same thing they are looking at. And when we start capturing "back" and "forward" button press events, we would capture them all and then somehow need to make distinction was it a nomral navigation and we should carry on and make full page reload, or maybe was it user changing URLs within the same root LiveView... That's sort of two sources of truth to me too, as both LiveView and Phoenix Router decides what should be rendered on what URL. I wonder if we need all that trouble, maybe what we need is something like Turbolinks - or even Turbolinks itself to handle transitions between pages? In your example, @josevalim tabs would have individual URLs, mapping to individual routes in Router, possibly initializing the same root LiveView with a different data representing different tab. When user clicks on other tab, full page gets reloaded by stealth, DOMs merged and user sees new tab. |
Very good points @hubertlepicki. I had a conversation with @chrismccord today and we have a new proposal that I submitted on #174 that (I believe) handles the concerns you brought up.
Just a tiny comment: in the approach proposed here, we would tie those two together so there is no duplication. We also do it in the new approach. Looking forward to the feedback on the new proposal. |
This issue describes the steps we need to take to improve the navigation story with LiveView. For example, if you have a LiveView with three tabs and as, the user changes tabs, you want to update the browser URL. Or, if you are navigating a table, you want to paginate it and annotate where in the table you are.
To implement this, the main function will be
Socket.push_path(socket, path)
. Oncepush_path/2
is called, the current path is compared to the one currently stored in the socket and, if they are different, the new path is sent to the client. Once the path arrives in the client, it is pushed to the stack withwindow.pushState
.A sample use of
push_path/2
would look like this:Note we may use a better name than
push_path
, as that can be confused in itself with a router helper. Similarly, we should also add areplace_path/2
, that triggersreplaceState
in the client side.On the client side, once the state is popped, LiveView will detect that, set the whole LiveView container to loading and send an appropriate event to the server. The event will send the host + path. On the server, LiveView will match the path against the router, extract the parameters, and call
mount
again.To implement this, we need to:
router.__match_route__/4
with a manually built connection. The desired parameters will be under path_parameters (this means we don't need to put path_parameters in the internal session anymore, we can always rebuild them)mount
again. However,connected?
needs to return false, which is counter intuitive. I recommend renamingconnected?
to something else.path_parameters
is becoming an essential part ofLiveView
, it probably makes sense to move them out of the session and make them an explicit argument to mount. We can probably name themmount(session, params, socket)
The text was updated successfully, but these errors were encountered: