0 Using VueJS with Rails: Using VueJS for Nested Forms in Rails: Part 2
I particularly like avoiding the extra complexity of a full-blown router-based SPA, especially when enhancing an existing Rails app. Thanks for the clear and concise walkthrough! It'll help me avoid several pitfalls that I suspect I'd have otherwise fallen into.
It worries me that the HTTP paths & verbs are hard-coded into the JS here. Would the next improvement be pulling those into data attributes, with values from the usual Rails URL helper methods? This might get us started down the road of reusability and decoupling, with the end goal perhaps being a gem that (like cocoon, or even the standard form builder) does some of the boilerplate for us.
<%= vue_form_with(model: @team) do %>
...
You can actually use rails form tags and put your vue element inside it and on submit, look up to the form for the url, the method, and csrf token.
The reason I didn't do that here is because the new Rails UJS library was throwing some JS errors for me because it was intercepting the button clicks inside the form. I didn't have time to figure that out so I just removed the form and did it manually. Meant to mention that in the video as that's the way I would ideally set it up.
Great stuff Chris, always manage to read my mind! Been playing around with Vue and Rails - definitely liking not having to go the full SPA route, for something that doesn't need to be one.
Really enjoyed this series, but I must say, I can't find any videos you did with a general Intro to Vue itself - just specific implementations. Could be useful for those Rails devs that haven't really dug much into what Vue can do for them (specifically I guess with a Rails context, as I know plenty of others out there with "Vue in 15 mins etc") - just a thought to round out the Vue series?
Cheers,
Nick
That's a fantastic idea Nick. I actually just dove kind of right into the deep end myself and it would be great to take a step back and show what it is and why you might want to use it. I'll definitely make a screencast on this!
This is a great mini-series on Vue.js. I had emailed you a while back that I was going with Ember but I am now 100% sold on Vue. This episode helped me apply all the Vue.js training I did through YouTube and Lynda.com to a rails app. Thanks Chris!
BTW, idea for a future episode with Vue would be two things: First, I would like to see how you would refactor this code. I assume you would put some of this into components if you were going to take this approach into production. Secondly, I haven't yet pushed a Rails / Vue project to production or anything with the new webpacker gem, so i would be curious to see you push one to production and see what changes would need to be made. I am still a little unclear about how the rails / vue / webpacker set up would be deployed. Thanks again!
Deploying Webpacker to production is as simple as making sure you have Yarn installed on the server. No other changes needed for it which is awesome! :D
Definitely will be doing more on Vue in the future.
You can always just grab the url from the wrapper form. The reason I didn't do that in these episodes was the rails_ujs library was doing something weird with the button clicks and so I left it out. Normally I would just use Rails to render a form tag and then use Vue to make it work, so then on submission Vue can just simply grab the url from the form (and csrf token too).
I've deleted the old profile, just reposting my questions.
-------------
Great introduction series Chris.
If I'm adding Vue to my current rails app will I need to write at the js all the actions for each form everytime, specifying the routes, redirects, etc?
This would be a lot of re-writing logic that it's already on the controller and should not "live" (or be duplicated) at the view level, don't you think? Is there a way to have more reusability, as mentioned by @@inopinatus:disqus ?
If you ask for JS back and you're using Turbolinks, it will actually send back a Turbolinks.visit() to redirect you on success which is awesome and means everything is handled like a single page app. You still have to handle the JS side for failure, but there's some talk about having that automated as well with some changes to Turbolinks to replace the current page with the standard re-render on failure. For now you have to just insert errors on the page manually.
I've deleted the old profile, just reposting my questions.
-------------
I see... And how about redirecting?
When working with .json, should the server's response include a "redirect_to" key?
And how about returning .js? Should the server's response be a update.js.erb with `window.location = ...` and the Vue js run the .js file?
Yep. And here's the link to the redirect_to override from the gem: https://github.com/turbolin...
I've deleted the old profile, just reposting my questions.
-------------
So I could use `Turbolinks.visit()` inside a js.erb file and make all the flow control and redirects using code at server side, right?
I do what I can. :)
I've deleted the old profile, just reposting my questions.
-------------
Amazing! Wow you're super fast replying!
Hey Chris, what actually controls the redirect after the team is created? Is is the window location in the js or the redirect_to in the controller html response? I'm using axios (as I believe vue-resource may not be supported going forward?) and disabled turbolinks. However, when I try to redirect to show my new item, it shows it loading in the logs, but the page doesn't change.
This line is what uses the JSON response and Turbolinks to redirect to the team page: https://github.com/gorails-...
And you should keep Turbolinks, it's awesome. :P
Thanks for this series! It gives a completely different view of Vue + Rails than most. It seems much more pragmatic than doing a SPA for part of a website.
Chris,
Can you give some ideas on how to deal with managing multiple Vue.js apps in a single application? For example what if the example rails app had other forms besides teams that need functionality (not necessarily nesting) and we want to develop that functionality using Vue.js as well.
Would you check for the existence of the html element and conditionally create Vue instances? For example, in hello_vue.js you write var element = document.getElementById("team-form"); if (element != null) { ... Would you just continue this pattern?
I have many js widgets and views in an existing Rails Application. These widgets get used on various views and sometimes more then once on a single view. Most of the time this javascript is enhancing an html element such as a table or input. My current js architecture is based on this article ( https://medium.com/@cblavie... ).
Would each of these widgets become a Vue app or is there another concept that I am missing?
Pretty much exactly what you mentioned. I am working on a video app that I'll be showing off more in the future, but it has a bunch of videos on the page and I wanted to use a Vue app for each one. I just selected all the elements that matched like ".video" and then looped over them and created a new Vue() app for each one. Works like a charm.
You won't need to check if the element exists in this case because it won't run the loop if there are no results so it may be a little more straightforward than selecting by ID which could return you null (and and why we have to check it).
Hm, that's cool, until you need to validate the form and show and handle all these nested validation errors. It requires much more efforts than the Rails nested_attributes.
And, as I see, Turbolinks doesn't allow you reuse the VUE form when you click the back button in browser, even if you use this TurbolinksVUE library. The form will be activated just once by VueJS, when the page was loaded. Check this out :)