I do not want to go into the extreme of moving entire form into frontend code. That brings encoding/decoding responses into JSON etc.
At the same time, I want to take benefit of the great UI libraries that these frontend frameworks produced. Those animations - those ARIA attributes, responsive design everything.
At this moment,
is the code we use for user login - using LiveView form management. My question is:
Can we replace <.input></.input> with a svelte component? LiveSvelte supports the same syntax. All we have to do is create a file input.svelte - import the UI library input component and render it with these props. Does that work? @chrismccord said that support for web components is in the pipeline post 1.0+ in Phoenix Liveview. Once that is done - probably there will be web components exactly meeting this need.
However, my question - can we use svelte components in similar lines?
I have never used svelte so I don’t know exactly what it does, only ever read the name.
But if it generates the HTML input field with the correct attributes, I do not see why it should not work.
Yeah. It occurred to me a bit lit - the weekend bit. I should have waited for Monday to post the question.
Thanks for sharing your experience. LiveSvelte and LiveVue introduced super convenient way to pass attributes and events just like you would for a normal phoenix component. That makes a real potent productivity enhancer in my view. So, was exploring about it. Before embarking on this path, I wanted to know from the experts if it is OK to tread on it.
I use Svelte + Phoenix in production. At the moment, it is very complex handling the errors in .heex templates. I use a hack:
There is a <data> element in HTML where you can embed your code/data, say as an alternative to ouputting JSON via an API.
My Svelte components use that as the complete source of truth. The form bindings use phx-feedback-for attribute which unfortunately cannot attach itself to Svelte components. So, I render some inputs inside an invisible div and parse that to display it in my components. I know that’s definitely not the best way to go about it, but, in a previous application I was forced to write an entire API endpoint just for this use case, so this does seem like the easiest approach for now. Unfortunately. I also heard that Phoenix team have deprecated phx-feedback-for and have introduced a shim for it called phx-feedback-dom.js. I somehow feel that it may contain the answers to our problems. I will write a guide for getting Svelte into Phoenix (my workflow) working sometime this weekend and share here, too.
Edit, here is the source code. At a quick glance, I think we can use this to get the error bindings:
Thanks @dsignr for the inputs. With LiveSvelte we are already able to pass properties to the component. We can handle events also inside Phoenix LiveView itself. So, things have improved significantly is what my belief is.
<.input field={@form[:email]} type="email" label="Email" required /> has nothing Elixir specific in it. So, I guess, rendering a Svelte component with the same syntax also should be possible. The svelte component can call the def handle_event('validate',...) on change. def handle_event('submit'. ...) should have the values in each of the svelte components. If that happens, we are more or less sorted I guess.
I am hoping at some point @chrismccord will make some time and outline his views on how to integrate WebComponents into LiveView 1.0. That view will have most solutions for us.
Thanks Mohan, I looked into LiveSvelte before. My issue with it is for a component definition, you have to touch both backend and frontend code for each component which I am not a fan of. I understand the entire LiveView appeal is based on that to be fair, but that is not my cup of tea.
Also, the setup was complex (when I checked it out a while ago) and looks like it is still the case. This is not to say It is not a great approach or anything, but when you do a production app, with frontend devs and backend devs, it causes access problems - Frontend devs need access to backend code. FOR ME if not a good approach.
My approach is using a WebPack build for Svelte and all components reside inside the assets directory. Components are injected by ID of each HTML element. The only thing I am yet to add to the code is handling of form field errors to the Svelte components. And Chris’s snippet looks promising. My backend code is completely isolated from the frontend setup.
You mentioned a very important point @dsignr. I could not articulate it correctly. The component definition is an issue.
So, you are using Phoenix in API only mode? Then aren’t things easier? I mean - unless you want to provide reali time validation on the forms - You can continue like regular frontend-backend apps? No?
What integration are you seeking? Curious. Sorry for too many questions. I am working on an app that probably many would have done on something like next or sveltekit etc. I ventured into Phoenix - and - now - struggling a bit for the UI components etc. So, curious to note experiences.
No worries, so I have tried the following approaches:
Pure Phoenix + LiveView
Phoenix + API + JS frontend
Phoenix + + Svelte
is obviously the easiest choice. However, it does not scale well for complex frontends for example stuff like custom CMS. In my experience this also means frontend and backend code is very much intertwined with lots of handle_events. In 6 months, you don’t understand your own code, this was the biggest drawback for me with complex applications.
This requires a tedious setup, potentially less secure as now you have to deal with access_tokens and what not, but gives the cleanest separation of frontend and backend code. I rarely use this approach unless my app really needs to have an API of some sort - maybe a Flutter application frontend. Not a fan of this approach for one person startups like mine. You have to deal with rate limiting the API, abuse, etc. This also has one downside where in you are forced to make additional queries most of the time for an object that already exists in the controller, which I am not a fan of.
This is a mix of 1 and 2 in the sense that you use any JS frontend you like, say pure Svelte (without Sveltekit). You define a component inside your assets/js folder and then call it inside your .eex templates. In case of pre-loading data in a form, say for a route that is used for editing resources, you can pass your backend object as embedded JSON inside a <data> element. This can be fetched inside your onMount inside your Svelte component. I consciously mentioned .eex and not .heex because calling Svelte components inside .heex seems to cause a clash and throw errors.
The final option is to use something like LiveSvelte, I am a little afraid to use it because previously I had used something similar (not related to Svelte) called Surface, on paper it provided lot of benefits but since I adopted it during its early development phases, I kind of burned my finger and have decided to take a wait and see stance on such new products.
Obviously, native Svelte support from Phoenix would be the best way to go about this, it was great seeing those tweets from Rich and Chris on this front, but then it would also mean making the framework too opinionated if they took that direction (what happens if someone is into Vue/Angular, it is now more work for them to use Phoenix to decouple from Svelte first).
For now, I am going to go with 3) and try to see if the JS snippet Chris shared helps add form field validation directly into my components (seems like it would) and will share my progress here. Hope this helps!
Thanks for the detailing.
Not sure I can agree with your criticism of one. Lack of UI components is definitely one drawback - but - just handle_events becoming complex - I am not sure. Maybe I have not handled that big a project yet.
Yes - two is definitely the least preferred choice. Most likely we are giving up all advantages that Phoenix as a framework gives.
I am curious to know how you implemented 3. I am wondering what is the big difference between 3 and 4 ( LiveSvelte). You might say the initial setup. But, once we move to vite for the entire setup - option 4 means only one setup - whereas option 3 needs to setups for handling assets.
Yeah, I used 1. in a large media company, it was my bad because enterprise CMS’es are complex and there are lot of workflows. Isolation of frontend and backend works best for it and you have the headache of having to deal with legacy frontend code as well.
LiveSvelte by itself looks really cool and I would probably try it in my next project. The only issue in my case is frontend code changes need backend changes as well, this maybe a unique problem to me because I have frontend only devs in my team to whom I would need to provide access to backend source code access as well, otherwise I become the bottle neck. It is more of an organisational hierarchy thing than the code itself.
Also, a lot seems to have changed since the last time I looked into LiveSvelte, looks a bit mature now. Either way, let’s see where this goes. Please do update us of your journey if you chose to work with LiveSvelte!
Hi! Just wanted to add my 2 cents. Look into the inertiajs project. It allows you to use React/Vue/Svelte and has a lot of nice goodies that make 2 a much more viable approach. It is also used by savvycal and this phoenix/elixir adapter is also maintained by them mainly.
It’s really late where I live but, damn, this seems like exactly what I was missing out. Thank you very much! Will spend the weekend trying it and update here.
Just a quick update, everyone. I tried the inertia.js using inertia-phoenix and I can confirm it’s pretty much doing 3. from my message above. Instead of a <data> element, it stuffs data into data attributes. However, if you look past this and the slightly tedious initial setup, it is actually so far pleasant to use. Will update more later once my integration is complete.
Hello! Thanks for the tag. I actually shared my views on Reddit. TLDR; I’m currently on InertiaJS with SVELTE 5.
It is overall a joy to work with. Why not LiveView? Well, if your frontend is heavy with complexity, LiveView isn’t best suited for it. Eg. Lots of contextual menus, drop downs, tabbed content and the like.
Having said that, my philosophy is to always start with a problem from LiveView’s POV. If It cannot be easily done with LiveView, then I go with InertiaJS + SVELTE.
Some drawbacks I found, but not directly tied to InertiaJS:
Sometimes there are memory leaks and it’s hard to find out.
Debugging could be better, but this has to do with SVELTE 5 more than Inertia. Inertia lives up to its promise.
I would start with Vue3 instead of Svelte 5 if possible. Again, due to very mediocre debugging experience and Vue has a larger ecosystem In general.
Should you give InertiaJS a try? Sure, try it out in a small project first. But, then again, always remember there is a penalty for maintainability when using JS codebases vs just pure LiveView. 6 months from now, you will have to allocate an hour or more to updating all the NPM packages and if there are version compatibility issues, then good luck.
So, my point is, try LiveView first if you can solve it using it. If not, then right now the best way to do JS frontend heavy work is using InertiaJS (for Phoenix). Hope this helps!
It really helps. Thank you so much for sharing your experience.
I read the reddit post. I understand that you like to keep the frontend and the backend separate (for more control, flexibility and better teamwork).
Its a great strategy for your use case.
Thanks again for sharing all the knowledge and experience.
– My Best.