Rails 3 - How to use stylesheet's compiled name inside javascript file? - ruby-on-rails

I have javascript file in rails app, where i pull in the stylesheet like this -
loadAssets: function(){
var stylesheet = document.createElement('link');
stylesheet.href = "<%= asset_path('lib/myStyles.css') %>";
stylesheet.rel = 'stylesheet';
stylesheet.type = 'text/css';
document.getElementsByTagName('head')[0].appendChild(stylesheet);
}
But asset_path helper used here, just gives plain myStyles.css name, where it should have been compiled name of that css file.
Because of this, i can't expire cache and get new myStyles.css file.
So, my question is, how can i get compiled name of this myStles.css file in my javascript file. Above code containing javascript file also gets compiled.

<%= asset_path('lib/myStyles.css'), :digest => true) %>

Related

How to call a javascript function inside a rails view?

I did just a upgrade from RAILS 5 to RAILS 6 and I see that all rails views are not able to call a javascript function as before in RAILS 5.
I have an external javascript file located under
app/javascript/packs/station.js
This is is embeded in in app/views/layouts/application.html.erb as
<%= javascript_pack_tag 'station' %>
This is the code how I call the javascrpt function from html.erb file :
<%= text_field_tag(:station_text_field, ... ,
onkeyup: "javascript: request_stations(); ") %>
When I try to call a function thats is part of the station.js then I get an error in the browser developmer view: ReferenceError: request_stations is not defined
But I can also see in the brwoser view, under Debugger :
Webpack / app/javascript / packs / station.js
and the javascript function I want to call.
So it seems that this script was loaded by the browser.
In contrast, when I just copy and paste these few lines that represent this javascript function direct into the template view file (...html.erb), something like :
<script>
function request_stations ()
{
alert("calling request_stations");
};
</script>
then - it works as expected !
By default, variables/functions defined inside JavaScript files that are packed by Webpacker will not be available globally.
This is a good thing, because it prevents global naming conflicts. Generally speaking, you don't want to reference javascript functions/variables from your view. You instead want to write JavaScript in a way that attaches functionality to DOM nodes using their id or other attributes.
Here is a basic example based on the code you provided:
# in your rails view
<%= text_field_tag(:station_text_field, ..., id: 'station-text-field') %>
// in your javascript
function request_stations() {
alert("calling request_stations");
};
const stationTextField = document.querySelector("#station-text-field");
stationTextField.addEventListener('keyup', (event) => {
request_stations();
});
Agree with mhunter's answer.
This post helped me get a grounding on this difference in Rails 6: https://blog.capsens.eu/how-to-write-javascript-in-rails-6-webpacker-yarn-and-sprockets-cdf990387463
What I don't see in your question is whether or not you did this in app/javascript/packs/application.js:
require("#rails/ujs").start()
require("turbolinks").start()
require("#rails/activestorage").start()
require("channels")
require("station")
The big difference in Rails 6 is that you have to deliberately:
require a JS file
deliberately export something from that file
deliberately import that something, in the file where you want to use it.
So if there is a function in station.js that you want to use, connect the steps above. Start with a simple function in station.js that fires upon DOMContentLoaded, and add a console.log("hey, station.js is alive and well"). If you don't see it, then something in those 3 steps is not right.
In pre-Rails6, you had a "garden" of JavaScript, just by virtue of being in the asset pipeline. In Rails 6, you have to be more deliberate.

Cannot get styles to load with Rails 5 & vue2-dropzone

I'm trying to get vue2-dropzone (version 3.0.3) to cooperate nicely with my Rails 5.1.4 app. I've added Dropzone to to my form and loaded the module but somehow I am not able to see the default styles. I don't think this is a problem with vue2-dropzone as much as with how webpacker loads the css.
My current setup:
application.js
import vue2Dropzone from 'vue2-dropzone'
import 'vue2-dropzone/dist/vue2Dropzone.css'
const myForm = new Vue({
el: '#multistep-form',
components: {
vueDropzone: vue2Dropzone
},
data: function () {
return {
dropzoneOptions: {
url: 'https://httpbin.org/post',
thumbnailWidth: 150,
maxFilesize: 5,
dictDefaultMessage: "<i class='fa fa-cloud-upload'></i> Drop files here to upload",
headers: { "My-Awesome-Header": "header value" }
}
}
}
and my _form.html.erb partial:
<vue-dropzone ref="myVueDropzone" id="dropzone" :options="dropzoneOptions">
</vue-dropzone>
I see that the Dropzone form is loaded. However, I cannot see the default style. I see the following in the console when I run :
Child extract-text-webpack-plugin node_modules/extract-text-webpack-plugin/dist node_modules/css-loader/index.js??ref--1-2!node_modules/postcss-loader/lib/index.js??ref--1-3!node_modules/vue2-dropzone/dist/vue2Dropzone.css:
[0] ./node_modules/css-loader?{"minimize":false,"sourceMap":true,"importLoaders":2}!./node_modules/postcss-loader/lib?{"sourceMap":true,"config":{"path":"/Users/myuser/Documents/apps/myapp/.postcssrc.yml"}}!./node_modules/vue2-dropzone/dist/vue2Dropzone.css 30.5 kB {0} [built]
I don't think it's an error since it says webpack: Compiled successfully. but I do think that webpack isn't loading vue2Dropzone.css for some reason. How should I configure webpacker to load that css file?
If I put the css file manually into my app/assets/stylesheets/ then it works without a problem.
Thanks in advance!
I think your CSS file should be loaded in CSS and not in js.
Here's how I'm doing it in my project.
Create application.css in packs folder and import into the Rails layout file, application.html.erb
<%= javascript_pack_tag 'application' %>
#import 'vue2-dropzone/dist/vue2Dropzone.css'
If you do this though, you will get an error because #import is a sass syntax. So you will need to do some extra webpack config.
You will find this post useful if you want to use css inside the application.js file.
https://medium.com/#mayorsan/rails-angular-webpacker-gem-like-a-pro-7cf40a588ab9

How to use rails webpack loaded js in js erb template

I am using webpacker gem in rails 5.0 app, but I can't get the javascript to execute/be available in the js.erb I'm hitting on validation error. I'm sure that I'm violating some simple premise here, but can't find the answer and no compile or console errors are present. I do have the <%= javascript_pack_tag 'application' %> in my application.html.erb
Here is the setup:
app/javascript/packs/application.js:
import * as CustomerSession from 'customer_sessions';
console.log('Hello World from Webpacker');
app/javascript/customer_sessions/index.js:
export { univgwTabs } from './univgwTabs';
app/javascript/customer_sessions/univgwTabs:
export let univgwTabs = () => {
console.log('hi');
};
js erb template called on validation error of form:
$("#right_side_right_bottom_target").html("<%= j render partial: 'generic_object_new' %>");
CustomerSession.univgwTabs();
Global.resizeWindow();
If there is no issue with console.log(CustomerSession) in the location where you are importing it then the simplest fix I found was to just assign the imported variable as one of the global windows properties.
// in packs/application.js (or wherever your pack is)
// import
import * as CustomerSession from 'customer_sessions';
// assign
window.CustomerSession = CustomerSession
Assuming that there is no issues with webpacker, you should now be able to console.log(CustomerSession) in the console or your js.erb file.

Rails Sprockets::CircularDependencyError with asset_path

In my application, I have javascripts, with a refer to default.html. I.e.
function link() {
var url = '<%= asset_path("sidenav/default/default.template.html") %>';
}
This works, but, when I use the same to refer with asset_path in another file, i.e. a html (.html.erb of course, and last script, too is a .js.erb), I receive the error Sprockets::CircularDependencyError. A example of html
<a ng-href="<%= asset_path('sidenav/default/default.template.html') %>">Default</a>
If I dont use the reference to default in javascript, html works, but if I use the same refer in multiples files, this error occur.
Any help?

asset_path returns wrong path for folder

I have .swf files under vendor/assets/images/swf/. I need the asset path of that folder.
But this (.js.coffee.erb)
#= soundmanager2
$ ->
soundManager.setup
url: '<%= asset_path "swf/" %>'
is rendering this (.js):
(function() {
var $ = jQuery;
$(function() {
return soundManager.setup({
url: '/swf/'
});
});
}).call(this);
I am using rails 4.0.0.rc1. I am on development mode. The path /assets/swf/soundmanager2.swf returns 200, while /swf/soundmanager2.swf returns 404. The helper image_path returns /images/swf/, but /images/swf/soundmanager2.swf also returns 404.
It is not worth the trouble, because you would have to disable digest to get the name of the files right. So the solution is to fix the library. In the case of Sound Manager 2, I did this:
Some CoffeeScript that I require:
#= require soundmanager2
jQuery ->
soundManager.swfNames =
"/soundmanager2.swf": "<%= asset_path('swf/soundmanager2.swf') %>"
"/soundmanager2_debug.swf": "<%= asset_path('swf/soundmanager2_debug.swf') %>"
"/soundmanager2_flash9.swf": "<%= asset_path('swf/soundmanager2_flash9.swf') %>"
"/soundmanager2_flash9_debug.swf": "<%= asset_path('swf/soundmanager2_flash9_debug.swf') %>"
soundManager.setup
debugMode: <% if Rails.env.development? %>true<% else %>false<% end %>
url: '/'
In my copy of soundmanager2.js (V2.97a.20130512), inside the definition of normalizeMovieURL:
url = ... // After url is set
url = sm2.swfNames[url]; // Workaround
on rails 4 all the asset helpers (image_path, asset_path and the likes) appear to only return a config.assets.prefix-prefixed path if the asset you're accessing is actually resolvable by sprockets.
put simply: it must exist in you asset path on the disk after precompilation.
therefore, asset_path('swf/') will not work since it is a directory and not a file.
also, i experienced the following: rails < 4 (sprockets, rather) copied original images (and thus swf files) and created a digested version of that same file. because of this soundmanager was still able to find the non-digested swf files even though i have config.assets.digest = true.
with rails 4, these original images are not copied anymore because they changed some precompile internals which leads soundmanager to throw up if it wants to fallback to flash.
to properly fix this soundmanager needs to be patched, like michelpm proposes.
for soundmanager-rails i started working on a fix including a proper patch for soundmanager which you can find over on github.

Resources