JavaScript File Per View in Rails

JavaScript file per view in Rails

Load the main JavaScript in application.js every time. Now create files for different needs. Create a form.js file, a myfancypart.js file etc. Don't load them in the application.html.erb layout. Load them dynamically when you need them:

application.html.erb:

<%= javascript_include_tag "application" %>
<%= yield :javascript_includes %>

top of your view.html.erb:

<% content_for :javascript_includes do %>
<%= javascript_include_tag "forms.js" %>
<% end %>

Everything in the content_for block will be loaded at yield :javascript_includes.

Rails - how to include Javascript files only on certain pages

You can put any Javascript files that you want to load manually in the public/javascripts/lib directory of your application, and they will not be included in the assets pipeline. You can then load them manually on the pages that need them.

For instance, in one project, I use the Chosen jQuery plugin, and I load it like so:

<script type="text/javascript" src="/javascripts/lib/chosen.jquery.min.js"></script>

Rails will source the public files from public/, so you only need to reference your files from there (remove the public/ bit).

This project is fairly large, with 88 controllers, 662 actions, and a total of 38 custom javascript libraries that get used sporadically around the app, including markdown editors, charting libraries, and even jQuery UI.

To manage the sprawl and to keep each page as tight as possible, I have done 2 things: 1) in my controller, I set an instance variable,@page_libs, to list the libs to load, and 2) the layout uses the values in @page_libs to include the specialty Javascript when required.

A controller action might look like this:

def edit
@products = products.find(params[:id])
@page_libs = [:ui, :textile]
end

And the app/views/layouts/application.html.erb includes this in the correct place:

<%- if @page_libs&.include?(:ui) || @page_libs&.include?(:table) %>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js"></script>
<script type="text/javascript" src="/javascripts/lib/chosen.jquery.min.js"></script>
<% end -%>
<%- if @page_libs&.include?(:swiper) %>
<script type="text/javascript" src="/javascripts/lib/idangerous.swiper.min.js"></script>
<% end -%>
<%- if @page_libs&.include?(:table) %>
<script type="text/javascript" src="/javascripts/lib/jquery.handsontable.full.js"></script>
<% end -%>
<%- if @page_libs&.include?(:textile) %>
<script type="text/javascript" src="/javascripts/lib/textile.js" charset="utf-8"></script>
<% end -%>

Note that the first include is for jQuery UI, which I load from a CDN, rather than from my app's public. This technique works just as well with external libraries, as well as those that you host. In fact, most pages in my app only depend on 2 external libraries (jQuery and Underscore.js), but have the option of loading up to 16 other Javascript libraries from external sources. Limiting external libraries on the page can significantly reduce your page load times, which is a direct performance boost for your application.

Sometimes, a Javascript library will include CSS components, as well. Or, you may even have page-specific CSS to include. The same approach can be taken with external stylesheet. These are the corresponding page-specific stylesheet "includes" for the above Javascript libraries:

<%- if @page_libs&.include?(:ui) %>
<link rel="stylesheet" type="text/css" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/themes/smoothness/jquery-ui.css">
<link rel="stylesheet" type="text/css" href="/stylesheets/lib/chosen.min.css">
<% end -%>
<%- if @page_libs&.include?(:swiper) %>
<link rel="stylesheet" type="text/css" href="/stylesheets/lib/idangerous.swiper.css">
<% end -%>

This way, I have a single point in the project to manage the libraries, regardless of how many (or few) are required for a page. I'll probably eventually create a series of custom before_action handlers in the ApplicationController to define which the libraries a page needs included. Something like this:

before_action: :include_library_ui,     only: [:new, :edit]
before_action: :include_library_swiper, only: [:show]

This would clean up the controller actions a bit more and make it easier to identify dependencies. However, given the size of my codebase and the pressing tasks remaining, I haven't taken this leap yet. Maybe it will inspire you to do so to start out.

Rails js files & Page specific js

Before body close tag and just after <%= javascript_include_tag 'application' %>

add <%= yield :page_scripts %>

Then anywhere (usually on top) in a specific view set your scripts with:

<% content_for :page_scripts do %>
<script>alert( "My nice scripts..." );</script>
<% end %>

How to require custom JS files in Rails 6

Get better-organized code and avoid multiple javascript_pack_tags in your application.html.erb file with this approach:

  1. Add your custom example.js javascript file to app/javascript/packs.
  2. Add require("packs/example") to your application.js file.

I would have liked to add a comment to Asim Hashmi's correct answer. But I don't have enough reputation, so I'll add my suggestion as an answer instead.

It isn't necessary to include the ".js" extension inside of the require.

Limit Javascript file to only be used in one page (Ruby on Rails)

You can use stub to tell Rails what's the file you don't want load despite using require_tree ..

For instance if your file text_message.js is in the app/assets/javascripts folder, then you can add the stub to your application.js file like:

...
//= require_tree .
//= stub 'text_message'

Then add your file to the precompile assets in your config/initializers/assets.rb, like:

Rails.application.config.assets.precompile += %w( text_message.js )

And then add it manually to your new.html.erb:

<%= javascript_include_tag 'text_message' %>

You need to restart your server with every change in the assets file.

How to put javascript code for rails view to assets/javascript folder?

Well, the way I see it, you're having problems mostly with mixing erb and js. I can help you with a easy way to deal with this.

Step 1: Instead of mixing ruby code and js code, you can render the ruby/rails variables (i.e @investment_updates) in a hidden input field in your html.erb view file. So, what's gonna happen is that the server will render your html.erb file first and it will already contain your variables "stored" in hidden input fields. Notice the JS code still hasn't started yet.

Step 2: Now you need to assure that you have a separate file with the js code. Let's say investment.js. Put it in the same folder as the application.js file and require your js file in the application.js:


//= require jquery
//= require rails-ujs
//= require activestorage
//= require turbolinks
//= require bootstrap
//= require investment
//= require_tree .

Step 3: Make sure you have in your layout file (probably a html.erb in a file inside views/layouts) the tag <%= javascript_include_tag "application" %> which is the code loading the application.js file in assets. That's the assets pipeline part of the question.

Step 4: Now to make it work. Once you assure this JS file is being loaded (try an alert or console in the beginning of the file), you can refactor your js code to manipulate the values already in the view file instead of dealing with ruby/rails variables. For instance:


//in investment.js
var index = $("#index").val(); //using the value already written in the view
animate(index, 0, 1);
...

Another approach, if you really want to mix ruby code with JS, would be to go about steps 2 and 3, but with the file named as investment.js.erb which can interpret ruby as well as JS. But instead of calling <%= javascript_include_tag "application" %> from the layout view, you can call <%= javascript_include_tag "investment" %> from the view you described in your question (it could be in the end of the file).
Approach 1 is more advised though.

Loading JavaScript in view in Ruby on Rails

Instead passing javascript_includes to yield, try just requiring your needed javascript file wherever you want directly in the view, something like:

<%= javascript_include_tag "headers.js" %>
<div class="vertical-center">
...

Your body in application.html.erb just like:

<%= render 'partials/header' %>
<%= yield %>
<%= render 'partials/footer' %>

And you could move the application.js file to the top, in order to preserve the Rails "structure":

<%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
...

Ruby on Rails renderin a view with static script files

It should be

<script src="/assets/js/myscript.js"></script>

Without the starting '/' it assumes the asset path is rooted on the page path.
With the starting '/' it assumes the asset path is rooted at the domain.



Related Topics



Leave a reply



Submit