Sorry, that’s not acknowledging that latency can become an issue, that’s acknowledging that using server-side rendering for things that don’t require a server isn’t the best of ideas (shocker, I know).
imagine an SPA for a basic CRUD system. there's a list view and details view with a delete button that returns you to the list.
in liveview server renders me the list view, i click details, server renders me details view, i click delete button, server renders me the list view.
if there's big latency/connection error/etc between clicking delete and getting back the rendered list - user just has to wait.
in spa i could optimistically assume that delete worked and render the list that i already have cached without the deleted item, allowing user to continue working immediately and if there was a disconnect/error - i could retry that delete in the background without bothering user, only prompting them after some number of retries.
don't see how could i implement this workflow in liveview.
You can do that in LiveView just as easily. Remove the item client side, then pushEvent to the server to handle the deletion. In case of any errors, notify the user, refresh the state .etc
pushEvent, pushEventTo (from client to server) [0]
> In case of any errors, notify the user, refresh the state .etc
so, "just use JS"?
every time you say "just use JS" you're diminishing the usecase of liveview because if i need so much js logic - why do i need to also use liveview if i can just use a framework/environment where i can share codebase between client and server seamlessly and have full control.
You stated don't see how could i implement this workflow in liveview.. I've presented you a way.
In case of any errors, notify the user, refresh the state .etc => This would all be done server-side and the client side would simply react automatically. The client side code in this case would have been minimal.
I don't think I'm diminishing anything. For quite a few years I was neck deep in React/Vue world. Now that I'm actively using LiveView, I can properly compare the differences between both approaches, cons and pros. For any new project, in the majority of cases I would pick Elixir with Phoenix LiveView instead of Elixir/Phoenix (backend) with React/Vue (frontend).
You’ve presented a workaround and a hack tbh, not something natively supported because the workflow doesn’t map to liveview model, which is fine but you have to be honest with yourself and acknowledge when stuff like that happens, otherwise you’re in for lots of fun down the line.
> For any new project, in the majority of cases I would pick Elixir with Phoenix LiveView instead of Elixir/Phoenix (backend) with React/Vue (frontend).
This could just be recency bias. New tech is always exciting, old tech is always linked to memories of all the issues you’ve had in the past.
I did a deep dive into liveview and this was my take away.
Its nice tech, but once you start introducing JS again to improve UX you really start asking yourself why you didn't just build it with react in the first place.
You could just delete the row with alpine or do a 3 line JS hook if you wanted to, it's quick and easy. That sounds a strange workflow though, it's generally better to make users wait for deletion.
isn't it funny that when you're trying to praise tech you like, all sorts of examples jump into mind, but when you try criticizing something you like - all that imagination vanishes and all existing examples can be dismissed as strange :)
I find it strange because that's not a behaviour I would use, but to each their own, it's the beauty of the web :).
If you really want to do it, you can add 3 lines on your project and that will work with any CRUD page you're building, I don't think that's unreasonable or difficult to do.
Edit:
Actually thinking about it, if you just made a form for that delete button and a phx-disable-with="" on the row it would probably work straight away without any JS hook.
surely you recognize that there is a gap in functionality between liveview and fully fledged frameworks that provide more granular control over ui interactions?
What exactly are you thinking in terms of latency becoming an issue under LiveView but not on normal requests?
Do you mean when websites just need a full refresh because they lost their requests on some callback and no-one implemented recovery across the 5 levels of callbacks or something more specific?
Well with Liveview you go "full server state" for everything that you would normally just use plain JS for. For instance, toggling a checkbox or collapsing a div.
Having latency on such lowlevel interactions might make the UI feel sluggish as a whole.
Yeah certainly, but I'm not sure people are using it that way?
Most examples are to show cool stuff you can do, they're not production vetted. Like most JS examples out there don't really mean that people should be publishing live credentials with their bundles.
I imagine in most cases one would leave everything that is not behind a logged in status as normal routes/pages (signin, landing, contacts, etc). Or if not that those would be things requiring a socket/real-time interface anyway.
For the interactions, I don't think you even need to use alpine.js. Plain setup on DOMContentLoad, CSS Dropdowns/collapsibles that are replaced on JS load, proxying LiveView DOM/Morphdom events (if needed) so other components (even vue,react, etc) can listen to them, and CSS animations.
import { setup_live } from "./phx/setup_live.js";
import { setup_dropdowns } from "./interactivity/dropdowns.js";
import { setup_collapsibles } from "./interactivity/collapsibles.js";
import { setup_links } from "./interactivity/links.js";
import { setup_inputs } from "./interactivity/inputs.js";
function setup() {
setup_live();
setup_links();
setup_dropdowns();
setup_collapsibles();
setup_inputs();
}
document.addEventListener("DOMContentLoaded", setup);
I went as far as having `onclick` handles and global window functions. Complete heresy. Yes, it's not 100% JS free, but it's pretty much low overhead.
Then LiveView is mostly for your admin dashboards and logged in users views, where it makes it pretty easy to do real-time feedback type of interactions/views and spa like navigation. Since you have proper auth and identification on the user, you can just log them off, rate-limit, block an account, and close their socket if needed.
From the top of my head not really, but this would depend on a few things:
- Is it a vendor lib ?
- It's not but is some particular file that is big enough to not make sense including on the root layout?
- It's neither, but functionality that can trigger multiple times and should be only once and only on those pages because it can conflict? or some variation of that?
I think they're all solvable but what makes sense will depend on those, but also on how you're using LiveView (is it LiveView only for logged-in users/some auth, can you set those on the live_view layout...)
But in some cases this is a problem also in spa's, where you have to use a snippet to check if the lib has been loaded, if not add a script tag to the body, or load it through js, etc...
When you need to go to the server, you go to the server. There's no other way around it.
I would be curious to hear how you solve this in other stacks? SPAs, whatever, when they need something from the server, they reach for the server.