#324 Passing Data to JavaScript
There are a variety of ways to pass variables from a Rails application to JavaScript. Here I show three techniques: a script tag, a data attribute, and the Gon gem.
- Download:
- source code
- mp4
- m4v
- webm
- ogv
For the routes, I use the js-routes gem quite extensively, it has always worked well for me.
Really happy to see Gon+RABL covered in this screencast. That has been my favored approach to passing data to javascript lately. Thanks Alexey for making the Gon gem (and integrating it with RABL) and thanks to Ryan for another great screencast.
I second was Eric has said above.
We need deeper nuts and bolts level advice on integrating Rails with Coffeescript/backbones/Twitter Bootstrap/datatables (or a grid/table display widget) in a javascript (jQuery really) centric environment. There is a nice article published on Backbone/Twitter Bootstrap which Mike Gunderloy linked in his "A fresh cup" column today:
http://coenraets.org/blog/2012/02/sample-app-with-backbone-js-and-twitter-bootstrap/
If something like this can be done in a Rails environment, it gives us enough of a framework to create a nice look and feel.
+1 for Backbone/Rails/Twitter bootstrap - very cool
re: Coffeescript/Backbone/Datatables - you might want to check out Slickback - a plugin that integrates Backbone and Slickgrid.
I'm thinking about using this technique to create a pop up for login. But not too sure how to procede (haven't tried yet, just thinking). I do know I need to send json from session#new function and use js to consume that and add it to the hidden lightbox. That's how I'm thinking about it, can anyone let me know if this sounds right...I'd like to use gon and possibly rabl too. Help appreciated.
"<%=j products_url %>";
products_url wasn't set as a variable anywhere. How did the above code get the url? localhost:3000/products
Why was the "j" necessary?
products_url comes from the routes, and j is a method to escape the output so that it can be used with javascript
Thanks for the railscast, Gon looks very promising!
My only fear is that google won't index anything more then 'Loading products...', making this technique unusable for certain projects. Are there any solutions known for this problem?
Looks good but seems to have a conflict with cancan (both current release and 2.0 alpha). Would post a bug report but not really sure which gem is the culprit.
On a brand new rails 3.2.1 app with only cancan and rabl added to Gemfile:
Anyone else seeing this?
Yes. I also have this issue. Rails 3.2.1 with rabl.
I am getting this error as well, though without cancan. Same trace to rabl/template.rb:66...
define in your gemfile that you need '0.6.0'. apparently they released a new version and somehow my gemfile thought it had to use 0.2.8. Which clearly wasn't compatible yet with rails 3.2.
one problem with using javascript tags is the 'j' escape function in rails doesn't work correctly or doesn't work how you might expect it to work. the string you send it is not always preserved and is corrupted in subtle ways.
for example if you have a string like:
and if you have:
then window.myvar == "<foo>"
the j function really has to replace '<' and '>' with '\u003C' and '\u003E'.
that should be:
then
Does gon work with jruby-1.6.5 ? Thanks
travis-ci told me that it works on all rubies, jrubies and rbxes
So gon did work for jruby. and I can alert the gon object from inside my coffeescript as a string. But when I assign the gon object(which is a json object) to my map, it does not pick up the data. I tried using the javascript tag and send a json object in the same way, and that works !
I'm trying to refresh a kendo chart with new data that uses gon variables as the data......it doesn't refresh the gon variable though with an ajax call! Any suggestions? I looked at gon.watch, but I need to update mutliple variables and it seems to work best with just a single variable and a time interval. I just need to refresh all the gon variables I have on the ajax call.
I'm trying to refresh a kendo chart with new data that uses gon variables as the data......it doesn't refresh the gon variable though with an ajax call! Any suggestions? I looked at gon.watch, but I need to update mutliple variables and it seems to work best with just a single variable and a time interval. I just need to refresh all the gon variables I have on the ajax call.
Does Gon work on production, when asset pipeline is on and js minified?
An if it does, how it works? Does it re-minified applications.js, I thought that application.js was cached through all requests.
Thanks,
alfredo
Exactly what I was looking for! Thanks.
Does anybody know how to use Gon in helper methods?
I have the same problem of benniemietz, gon variables doesn't refresh after ajax call, I tried with gon.watch, reset and reload without success. Anybody has a suggestion?
It seems to me this railscast is presenting the incorrect way to put content into javascript variables.
If you are trying to put a template variable into a javascript variable inside an HTML template, the syntax is actually not very intuitive:
You have to flag the string as safe for raw output into the html document, but also apply javascript escaping. Otherwise, if @foo contains "<foo>" then your final document output will be:
Which is almost certainly not what you want.
However, if you use html_safe but forget to apply the javascript escaping, you are opening yourself seriously to javascript injection attacks. So this is stuff that must be done very carefully in order to be done both correctly and safely.
IMO it is unfortunate that apparently no authoritative documentation or respected tutorials point this nuance out, and that Rails has no better, more intuitive way to put content safely and correctly into javascript strings...
Actually, furthermore you really should be adding a to_s on @foo:
Because if there's any chance @foo might not be a string, you'll get a NoMethodError trying to call html_safe on it.
I'm gonna go out on a limb here and wager that most Rails devs are not applying these three (count 'em, three) conversions on their values in order to splat them into a script?
html_safe
is usually automatic. It's not generally necessary to call it explicitly. See http://yehudakatz.com/2010/02/01/safebuffers-and-rails-3-0/Actually, none of this is particularly correct. See my comment below regarding a way to do this without mixing JS, HTML, and Ruby.
Also,
var foo = '<foo>'
is actually the correct XHTML way of representing the JavaScript forvar foo = '<foo>'
(unless you're inside a CDATA section). The character entities are substituted before the JavaScript is evaluated. HTML, however, accepts<
and>
within a<script>
element (which I didn't realizeāI thought they were invalid, but http://validator.w3.org tells me that they are OK).How can you actually load in the comments inside of the div?
Passing data to Javascripts through data attributes looks like an especially useful solution to my problem: I'm intending to use this technique to dynamically generate content for multiple popovers.
But I'm left with this question: how is the content file itself set up? As a partial in the same directory as layout referring to it?
I like the idea of Gon, but it mixes JavaScript into the generated HTML, and therefore is not advisable to use. The proper way to pass variables from Rails to JS is as follows:
This way, your HTML output contains only HTML (JSON is simply text data, after all), and your JavaScript files contain only JavaScript. And that's the way it should be for separation of concerns (see also http://stackoverflow.com/a/7987959/109011 and http://stackoverflow.com/a/8819511/109011).
Thank you so much. Simple, elegant, better.
How could you use the retrieved data as CSS attributes or element names?
1)
Once I have the rails data in js, how would I use that value to set the width of a vote bar div to that calculated percentage value?
Something like
$('.vote-bar').css("width", "#{percentage}%");
But I know the syntax is not right.
2)
How could I also use the rails text data as the name of a class? If my rails data returns 52 via json, I want to select an element named $('#item-52') in js...
What is wrong with my coffeescript?
The
JSON.parse
line is causing the site to fail.I cannot use
var
either.jQuery ->
$percentage_neti = JSON.parse($('#vote-data'))
$('.bar-neti').css("width", $percentage_neti + '%')
(the last two lines are indented)
The more correct variant of this approach (using a data- attribute) was already covered the screencast. Nothing to see here. Move along.
It works perhaps if you use text method of jquery object :