I have a variable in rails controller like
def index
@approveflag = true
end
I need to access this variable in my javascript code, I used the code given below in index.html.erb
<script>
alert("<%=@approveflag%>")
<script>
It works fine with result "true".But when I moved this code to its corresponding .js file it gives an alert with result string ""<%=@approveflag%>"". What is the reason. How can I solve this?
Thanks in advance.
Rails uses a technique called "Unobtrusive JavaScript" to handle attaching JavaScript to the DOM. This is generally considered to be a best-practice within the frontend community, but you may occasionally read tutorials that demonstrate other ways. When clicked, the link background will become red.
.js.erb files are for controller actions, such as create, when you want javascript to be executed when the action completes. For example, when you want to submit a form via ajax and want display an alert when everything is done, you would put the $('#business_submit'). click(...) in your application.
Rails UJS (Unobtrusive JavaScript) is the JavaScript library that helps Rails do its magic when we use options like remote: true for many of the html helpers. In this article I'll try to explain the main concept of how this works to make it transparent for the user.
I personally don't like mixing js with erb so I would do something like this:
in index.html.erb
<%= content_tag :div, '', id: 'mycontainer', data: { source: @approveflag } %>
in js
$('#mycontainer').data('source')
alert($('#mycontainer').data('source'))
And you have the value from that instance variable, you can add a data attribute in a link_to if you want.
You cannot use the js
files for this, they are part of the asset pipeline, they are compiled/compressed, and preferably only downloaded once by your client (browser). So they should not change. So at the time the js-files are precompiled, the instance variable is not set and would not make any sense anyway.
But there are a few options.
You can declare a javascript variable in your view, which your javascript can use (for global data)
Code (I use haml):
:javascript
var approveFlag = #{@approveflag} ;
You can declare data-tags on elements, if the data belongs to a specific element. But for instance, you could also a data
-tag on body
element
For instance
%body{:'data-approveflag' => @approveflag}
Or something like
= link_to 'Collapse', '#', 'data-collapse-div' => 'class-to-collapse'
Alternatively you can use ajax/json to download the data. This is clean, but adds an extra delay, so only do this is if the data is not required immediately.
I recommend that you to use the 'gon' gem
I'm usually more oriented to straight options that don't imply installing, but trust me using 'gon' is very direct and clean
In your Gemfile add this lines
# To use controller variables as javascript variables
gem 'gon'
Do a bundle install to get/install the gem
In your app/views/layouts/application.html.erb add the following line
<%= include_gon %>
Then in your controller pass your variable to gon as simple as this
gon.your_variable = @controller_variable
And in your javascripts retrieve your variable (in this case to show an alert)
alert (gon.your_variable) ;
And That's it !
For more examples and details see the Wiki page - https://github.com/gazay/gon/wiki
In my project I need sometimes user language related translations. So what I did is, I created a simple js file to store the localized text:
var TRANSLATION_ARRAY = []
function store_translation(key, value) {
TRANSLATION_ARRAY[key] = value
}
function get_translation(key) {
return TRANSLATION_ARRAY[key]
}
In den index.html.erb or other components I do this to store the localized text:
store_translation('text_id', "<%= translate_with_user_language('text_id') %>")
In my plain js file located in app/assets/javascripts i get the localized text by:
get_translation('text_id')
Works very well. You can use this approach also for other purposes not only translations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With