Rails ERB Inside Javascript - javascript

I'm trying to use some View instance variables inside Javascript.
My JS file is included in the head tag of my HTML. And it's a *.js file in assets/javascript.
When I try to...
console.log(<%= #some_instance_variable %>)
... I get syntax error. And if I try to...
console.log('<%= #some_instance_variable %>')
... the output is just the string <%= #some_instance_variable %>. How can I do to obtain the instance variable's actual value?. I'd really appreciate any help!.
Regards!.

You can include it with:
<%= javascript_include_tag('file_name.js.erb'.sub('.erb', '')) %>
But in fact it's a very ugly solution. If you want to use rails variables in JS scripts, use gon gem.

Related

How to get a Rails variable into JavaScript file (D3)

I need to grab data from by database and pass it to JavaScript file in my Rails 5 app.
In my controller I create a variable that looks like:
#this_anomaly = Anomaly.find_by_id(2)
I can obviously access it as well as in my view with something like:
<%= #this_anomaly.started_at %>
But I need to get that same data into my javascript file, which I use to draw graphs in D3 to inject into my view. How do I pass it through?
Not sure where to start, thanks!
You could declare your javascript variable in your html.erb like
var started_at = <%= #this_anomaly.started_at %>
One option is to put the data in your HTML in a data attribute
<div data-started-at=<%= #this_anomaly.started_at %> data-for-d3-graphics></div>
Then in your js file
let value = $('div[data-for-d3-graphics]').data('started-at');
I'm not sure if that is the exact syntax for .erb files, but you get the idea
So one method that I tried that works (since I'm using d3) is to request the data in my html.erb with:
<div id="anomaly_data">
<%= #this_anomaly.started_at %>
</div>
Then in my js file, use d3.select to store it in a variable:
var anomaly = d3.select("#anomaly_data").text();
Which works and gets me the date/times/etc without putting them through any processing! But, there must be a better way?

Coffesscript variables in ruby code pieces

I'm just trying to call rails helper from my coffeescript.
The problem is that coffee variables are unavailable in ruby code pieces that are in <%= ... %> blocks. And if they are processed with #{} it translates to JS in a wrong way.
So, let me illustrate. This is a piece of .js.coffee.erb file:
<% environment.context_class.instance_eval { include InputsHelper } %>
$('#input_input_type').change ->
t = $('#input_input_type').val()
$('.input_address .help-block').html('<%= input_type_hint(t) %>')
This code produces such error: undefined local variable or method 't' for #<#<Class:0x007f5e75ebd860>:0x007f5e785d1410>
Ok, let's put 't' into #{}:
<% environment.context_class.instance_eval { include InputsHelper } %>
$('#input_input_type').change ->
t = $('#input_input_type').val()
$('.input_address .help-block').html("<%= input_type_hint(#{t}) %>")
This translates to JS in a wrong way. The last string looks like this:
$('.input_address .help-block').html("<%= input_type_hint(" + t + ") %>");
Quotes are broken, so it causes rails to fall with the error:
syntax error, unexpected ';', expecting ')' ; _erbout.force_encoding(__ENCODING__) ^
In that way I don't know how to manage with this. Is there any way to do it?
There is no easy way to do this.
The problem is that the coffee script executes in the browser, but the stuff in the <%= ... %> executes on the server while the server builds the coffeescript.
So when you say input_type_hint(t) this is running on the server, but the poor sad server doesn't have a clue what "t" is.
To make this work you are going to have recode the entire input_type_hint method in coffeescript, so that it can run in the browser too! (and then it won't be in the <%= => thingy.
By the way you might want to check out http://ruby-hyperloop.io as instead of using coffeescript you just write ruby everywhere, and you basically don't need this clumsy ERB business.

Passing a local variable into another view's JS - Rails

Is there a way to grab / fetch a variable inside js between two different views? Say I have an index view with does:
<% foo.each do |foo| %>
<%= link_to 'bar', bar_path %>
<% end %>
Then in bar I want to add some jQuery to a specific element with foo.id selector:
$('div#<%= foo.id %>').fadeOut(); // I know the interpolation wouldn't work here
I know I can pass foo.id to bar with my path or send it via the locals hash, but how would I "grab" it with jQuery?
You can easily pass variables to JS using a gem called gon.
gem "gon"
All you have to do is add this gem to you Gemfile and then you can call gon inside any controller like this:
class PaymentsController < ApplicationController
def new
...
gon.controller = "payments"
gon.action = "new"
gon.message = "Hello World!"
...
end
end
And now, at any javascript (in following case, coffeescript) you can:
$ ->
# Check if it is the target controller and action
if gon? && gon.controller is "payments" && gon.action is "new"
alert gon.message
Is there a way to grab / fetch a variable inside js between two
different views
Not without hacking.
JS is an client-side technology, meaning it loads in the browser, not on the server. This is famous for causing so many issues for developers trying to bind to dynamically-named objects, much like what you're trying to do.
There are several ways around this. I'll go through them for you:
Class
The first way is to use a broader identifier, such as element type or class.
You're currently trying to select foo.id, which means you're going to have to pass that data directly to JS somehow. Inefficient.
A much better way would be to use something like this:
$("a.bar").on("click", function(e){
$(this).fadeOut();
});
--
URL
According to this resource, there are no inbuilt ways to pull query strings from JS: How to get the value from the GET parameters?
You may be able to do something like this:
$(document).ready(function(){
foo = window.location.search.substring(1); //Considering you have http://url.com/your/foo/id
$("#" + foo).fadeOut();
});
--
ERB
There is a final alternative, although this only works if you don't precompile your JS (which I'm not sure is actually feasible any more). That is to use ERB directly in your JS, rather like what you've done in the question.
Whilst this works for dynamic references (such as paths), I don't think it can pull data from a controller. Unless, of course, you put the script directly in your view - which goes against the conventions of MVC.
#app/views/bar/show.html.erb
<script>
// your code here
</script>
I think you need to create a js.erb file and in that pass a variable defined in your controller action.
The code insde js.erb would look like this :
<% fields_html = render "fields", :entity => #model %>
$("#fields-list").html("<%= escape_javascript fields_html %>")
Here fields is a partial I have created. :entity is basically passing of the variable value. #model is the variable defined inside controller action. fields-list is the id of the field I want to load using jquery.

pass a parameter from a views to a javascript

I have the next variable in my main_controller.rb:
def create:
#token = "24vgd32"
end
in my views/create.erb, I wrote:
<%= javascript_tag do %>
window.my_token = '<%= j #token %>';
<% end %>
by this way, I can use this variable in any of the JavaScript files that this page references.
but how can I use it in my application.js?
this is my application.js:
$(document).ready(function(){
licensario.getLicense({
wizardToken: my_token
});
});
any help appreciated!
In your create.html.erb use this
<%= hidden_field_tag :my_token, #token, :id => 'some_field_id' %>
replace the some_field_id and my_token with desired names.
In your javascript file
$(document).ready(function(){
token = $('#some_field_id').val();
//use your token for any other means.
});
I see 3 ways :
You can use erb in your js file, naming it application.js.erb. However, the data you want to pass must be available when the file is compiled, so this is probably not what you want to do;
You can make a XHR request to your server to fetch the value you want;
You can embed the value in the dom of your view. Some will suggest using a hidden field, I rather tend to use data attributes. For instance, <body data-my-value="32">.... You can retrieve it in your js by doing $('body').data('my-value'). Be careful to call this once the dom is loaded.
I tend to use the latter.
window.my_token makes my_token a variable on the global scope; once it's been defined it is available to application.js as simply my_token.

Returning javascript from rails helper

I am having problems returning javascript from helper functions. I am unable to get the following test case to work:
function in helpers/application_helper.rb
def show_stuff
return '$("div#flash").html("<p> stuff </p>");'
end
now I try to call this helper function in general.js.erb
<%= show_stuff %>
Here is the output
$("div#flash").html("<p> stuff </p>");
I've also tried show_stuff.html_safe and raw show_stuff and had no luck. I feel the issue is Rails auto-escaping html but have been unable to find a solution.
ERB is escaping the characters in your outputted Javascript.
To prevent this happening use the raw method in your template.
<%= javascript_tag do %>
<%= raw(show_stuff) %>
<% end %>
I've added the javascript_tag method around this for context.

Categories