Rails: pass data to javascript [duplicate] - javascript

This question already has answers here:
How to pass Ruby variables to a JavaScript function in a Rails view?
(6 answers)
Ruby on Rails - Send JavaScript variable from controller to external Javascript asset file
(2 answers)
Closed 8 years ago.
i'm new in Rails and in a controller i have:
class PagesController < ApplicationController
def home
#temp = "Hello"
end
end
I have read that i must put the javascript code in application.js (tell me if true) and i have:
window.onload=function(){alert("<%= j #temp %>")}
Obviously that alert print the string "<%= j #temp %>"
How can i pass the variable #temp to the javascript so that the alert can print Hello?
Thanks

I wrote an article on how to pass Ruby objects to the client. Ryan Bates also has an excellent RailsCast on passing data to JS.
Add a div to your view that corresponds to your the PagesControlle#home action that will not be visible when you load the page but will contain the data stored in the Ruby objects:
# views/pages_controllers/home.html.erb
<%= content_tag :div, class: "temp_information", data: {temp: #temp} do %>
<% end %>
Load the page with this div included and view the page source. You can see your Ruby objects stored in the .temp_information div. Open up the JavaScript console to access the Ruby objects as JavaScript objects:
$('.temp_information').data('temp')
You do not need to add your JS to a JS partial, you can also use the asset pipeline.

I do something similar to, but simpler than gon. I have the following in my ApplicationController.
def javascript_variables(variables)
#javascript_variables ||= {}
#javascript_variables.merge!(variables)
end
Within a controller action I can then do something like
def some_action
javascript_variables(user: current_user)
end
In my ApplicationHelper I have something like this
def javascript_variables(variables = nil)
#javascript_variables ||= {}
#javascript_variables.merge!(variables) and return if !variables.nil?
output = ''
padding = #javascript_variables.keys.group_by(&:size).max.first
#javascript_variables.each do |variable, value|
output << "#{variable.to_s.ljust(padding)} = #{value.to_json},\n "
end
raw "var " + output.strip.html_safe.gsub(/\,\Z/m, ';')
end
and finally in my layout's <head> I have
<script>
<%= javascript_variables %>
</script>
This gives me something like this (from a real example in my application)
<script>
var pageModule = "site/index",
isCustomer = false,
utype = "normal",
isAnonymous = true,
keyboardShortcuts = false,
pubnub = null,
requestToken = "3zj974w074ftria3j";
</script>

Take a look at this.
http://tech.thereq.com/post/17243732577/rails-3-using-link-to-remote-true-with-jquery-ujs
One of the easiest ways is to use js.erb file, where you can do ruby tags to access variables that you defined in the controller action.
You need to use a respond_to block in the controller action, specifying the action to be able to respond to javascript.
items_controller.rb
class ItemsController < ApplicationController
def action
respond_to do |format|
format.js
#format.html {} # These are for allowing other types of formats to be responded to.
#format.json {} # But they are not necessary for using this js.erb way of doing things.
end
end
end
/views/items/action.js.erb
$(div).html('The cat has erased your page');

Related

How to append ruby code to html element

I'm making a chat using ActionController::live.
stream in my ChatsController pushes posts.
def stream
response.headers['Content-Type'] = 'text/event-stream'
start = Time.zone.now
loop do
Post.where('created_at > ?', start).each do |post|
response.stream.write("event:push\n")
response.stream.write("data:#{post.to_json}\n\n")
start = post.created_at
end
sleep 2
end
rescue IOError
ensure
response.stream.close
end
Using javascript, I wrap gravatar and this json with <li> and append this to <ul>. Then, I want to use gravatar_for method I defined and render partial for post model.
Would you teach me how to append ruby code (<%...%>) to html elements()? I tried to .append('<%...%>') once, it didn't work.
If your controller is responding to javascript, you can render a partial using from the corresponding js.erb file like so:
$('element').append('<%= escape_javascript(render partial: "post") %>');

How can I render via CoffeeScript in Ruby on Rails 4

I was trying to solve this problem for a while with no result.
I've wanted to pass variables and load a render into a div using CoffeeScript in rails 4.
(I'm using SpreeCommerce platform).
view:
<%= link_to taxonomy.name,root_path+'t/'+tid, {class: "uno", remote: true} %>
controller:
respond_to do |format|
format.html
format.js # menu.js.coffee.erb
end
menu.js.erb.coffee:
$('div#productos').html("<%= escape_javascript(render :partial => /shared/products) %>")
I'd like to load the page '_products.erb.html' and the partial processes the variables that I give it. As soon as I know, view and controller are ok, the problem is in menu.js.erb.coffee
Any help will be apreciated!
ADDITIONAL:
I've modified the extension to .js.coffee.erb. When I try to run the app, it shows me:
"undefined method `render' for #<#:0xa70317c>"
I tryied using <%= raw escape_javascript( render :partial =>... almost always "render" method give me problems.
NEW INFO:
I added gem 'coffee-script' to the Gemfile (then 'bundle install').
Now, when I click the link_to, it shows me into the HTML <%= escape_javascript(render :partial => /shared/products) %> as a text instead of loading the "partial"... any suggestion please?
I wrote a post about this after struggling through the same problem.
You need to:
Name it menu.js.coffee. Suffixing .erb causes it not to be evaluated as CoffeeScript.
Use raw to escape it.
I used these two on my website. Here's how it looks:
<%= raw render 'path/to/menu.js.coffee' %>
It still processes ERB within your CoffeeScript.
I would recommend changing it from menu.js.erb.coffee to menu.js.coffee.erb.
Rails will process the file extensions from right to left. Meaning right now, your file is treated first as coffeescript, then as ruby, and finally as javascript. It looks like you want to make the ruby substitutions first, then parse the coffeescript into javascript, so that would be menu.js.coffee.erb
First of all, you should change file name from menu.js.erb.coffee to menu.js.coffee.erb and you need configuration file as follow, which is a contribution by cervinka on coffee-rails issue #36
config/initializers/coffee_erb_handler.rb
ActionView::Template.register_template_handler 'coffee.erb', Coffee::Rails::TemplateHandler # without this there will be template not found error
class ActionView::PathResolver < ActionView::Resolver
EXTRACT_METHODS = %w{extract_handler_and_format_and_variant extract_handler_and_format} # name for rails 4.1 resp. 4.0
method_name = EXTRACT_METHODS.detect{|m| method_defined?(m) || private_method_defined?(m)}
raise 'unknown extract method name' if method_name.nil?
old_method_name = "old_#{method_name}"
alias_method old_method_name, method_name
define_method(method_name) do |path, default_formats|
self.send(old_method_name, path.gsub(/\.js\.coffee\.erb$/, '.js.coffee'), default_formats)
end
end

How can pass data/variable from file_controller.rb to application.js

I have
#send_variable = 'show value in alert'
in controller file. In application.js, I want to do something like :
var receive_variable = <%#send_variable %>;
alert(receive_variable ); >>> screen show 'show value in alert'
how can I do this ?
Your #send_variable won't be available in application.js because it's a javascript file. You do however have the option of alerting the value placed in a hidden div once your action template is rendered.
Something like follows:
# Controller
def action
#send_variable = 'show value in alert'
end
# app/view/action.html.erb
# Note in your 'hidden' css class you need to set it to 'visibility: hidden;'
<%= "<div id='send_variable' class='hidden'>#{#send_variable}</div>" if #send_variable %>
# app/assets/javascripts/application.js
$(document).ready(function(){
$(document).on('load', '#send_variable', function(evt) {
alert($('#send_variable').text());
});
});
Another approach is to use remote: true in either your link or button that calls this action. Doing so will make a ajax call to the action and you can use the js format to execute your js action view template.
Something like following:
# Controller
def action
#send_variable = 'show value in alert'
respond_to do |format|
format.js
format.html
end
end
# app/view/action.js.erb
alert("<%= j #send_variable %>");
Add = to print
var receive_variable = '<%= #send_variable %>';
alert(receive_variable );
or just
alert('<%= #send_variable %>');
Also, check http://javascript.crockford.com/code.html for JS conventions
In your javascript, you have to enclose the instance-variable (#send_variable) with quotes.
alert('<%=#send_variable%>');
Assuming that #send_variable is a something like integer, the quotes ain't necessary.
This should do.
Have a look at the 'gon' gem (https://github.com/gazay/gon), which allows you to set javascript variables from anywhere in your rails code, using something like gon.variable_name = value, and subsequently use it in any javascript, like gon.variable_name. I used to use the above mentioned techniques, but 'gon' makes it all much easier, as it literally acts as a window between rails and javascript

How to make a global JavaScript File for Ruby on Rails 3which gets some content from Rails with <%= ... %>

I have a model with lots of parameters and a function giving all the parameter names. Now I'd like to have a global Javascript file using this function like this
function bar() {
<% Model.parameter_names.each do |name|
parameters.push("<%= name %>");
<% end %>
// do something with them
}
The *parameter_names* method is a Class Method (*def self.parameter_names*), so i do not need an object.
Is this possible?
You can, sort of.
First of all, if you are thinking about a javascript file included like this :
<script src="your-js-file.js"></script>
You can forget about it. In no way, RoR is doing anything for that file.
You can mix javascript with RoR in controller responses because that js file is read by RoR, then evaluated for any Ruby expressions, then returned as the response to your browser. In fact, if you take a look at the js response from the controller for something like you wrote :
function bar() {
<% Model.parameter_names.each do |name|
parameters.push("<%= name %>");
<% end %>
// do something with them
}
you would see something like :
function bar() {
parameters.push("abc");
parameters.push("def");
parameters.push("ghi");
parameters.push("jkl");
}
Javascript is a client side technology. The only way to add server side code in it is to actually generate the js file with server side code. This is probably your best shot at it.
Controller :
def jsfile
#variable = "hello, world!"
respond_to do |format|
format.js
end
end
jsfile.js.erb
function bar() {
alert('<%= #variable %>');
}
Include the javascript file like this :
<script src="<%= jsfile_controllername_path %>"></script>
And add the corresponding route in routes.rb
Create the Javascript array in the head of your layout and then reference that in your global JS file.
Layout example (HAML):
%html
%head
:javascript
var parameter_names_array = ['#{Model.parameter_names.join(', ')}'];
Global JS file
function bar() {
// do something with "parameter_names_array"
}

How can I pass to Ruby obj to Javascript?

I have this to calling the choose_category:
{ :action => :choose_category, :id => category } do %>
And I have this method to calling the choose_category.js.rjs:
def choose_category
begin
category = Category.find(params[:id])
rescue
ActiveRecord::RecordNotFound
logger.error("Attempt to access invalid product #{params[:id]}")
# flash[:notice] = "Invalid product"
redirect_to :action => :index
else
respond_to { |format| format.js }
# redirect_to_index
end
end
I want to call back the category name, how can I do that? I try this, but it return nothing for me.
page.alert(#category.name)
Your problem is that #category isn't defined in your RJS template.
RJS files are essentially views that generate Javascript. Like views, they have access to instance variables set in the controller, but not local variables.
Putting this in the begin section of your action should solve your problem.
#category = Category.find(params[:id])
I'm not sure of this since I'm not very familiar with js and rjs, but I would add to your rjs something like this:
category_name = <%= #category.name %>;
and then
page.alert(category_name)
or just:
page.alert(<%= #category.name %>)
If you can write your own JavaScript why not use the Ruby's to_json() method to output your object in JSON to an embedded constant on your page and then write some JavaScript to access this variable and manipulate as needed?

Categories

Resources