I'm using Rails 6 with bootstrap and webpack. everything was working fine. Bootstrap works, jQuery works, etc until..
I'm following this acts_as_votable tutorial: https://blog.makersacademy.com/how-to-make-a-dynamic-rails-like-unlike-button-using-the-acts-as-votable-gem-9ab71686ff82
When the PostController likes the post it goes into the like.js.erb and then in the browser returns the error
Uncaught ReferenceError: $ is not defined
at <anonymous>:1:1
at processResponse (rails-ujs.js:282)
at rails-ujs.js.195
at XMLHttpRequest.xhr.onreadystatechang (rails-ujs.js:263)
jQuery is working though as I have bootstrap working with no errors. its only when it comes in thru the ajax that it seems to be missing it.
in PostsController:
respond_to :js, :html, :json
def like
@post = Post.find(params[:id])
if params[:format] == 'like'
post.liked_by current_user
elsif params[:format] == 'unlike'
post.unliked_by current_user
end
end
in like.js.erb:
$('.liked-btn').on('ajax:success', function(){
$(this).parent().parent().find('.like-count').html('<%= @post.get_likes.size %> &128591');
$(this).closet('.liked-btn').html('Like');
});
$('.like-btn').on('ajax:success', function(){
$(this).parent().parent().find('.like-count').html('<%= @post.get_likes.size %> &128591');
$(this).closet('.like-btn').html('Liked');
});
The 'likes' appear to be registering its just the return ajax and javascript that errors out. The routes seem fine as per the tutorial.
One funny thing is in my controller i mistyped "respond_to" as "responds_to" and it gave the error @posts.get_likes method not known for nilClass. Which means it did not blow up on $ symbol and understood jquery just fine in that instance. so something in the controller is causing this? (never mind on the funny thing it was probably just the ERB getting processed before the javascript was being run)
Note: I also tried replacing $ with jQuery and got the same error, except with jQuery unknown at that time.
Okay this appears to be due to the fact that even though jQuery is loaded it is not visible from the view (whatever that means honestly this isn't my area of expertise).
So my tests were showing jquery loaded, as it was. But it was only visible to webpack? I guess?
The fix is to add the following to your app/javascript/packs/application.js
import $ from 'jquery';
global.$ = jQuery;
Once this is done, the view can then see the symbol pointing to jquery.
Now my app already had the following in config/webpack/environment.js
const { environment } = require('@rails/webpacker')
const webpack = require("webpack")
environment.plugins.append("Provide", new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
Popper: ['popper.js', 'default']
}))
module.exports = environment
But apparently this is not sufficient to be seen from the view. It does however let turbolinks/bootstrap/etc work fine.
So maybe there is a better place to put the shortcut symbols where it is seen by both, but I'm not sure. As of now the entry to application.js gets it all working.
It should be noted that I did find information that "expose-loader" could help jquery be seen locally but I could not get that to work.
Referencing these posts for the fix:
For reference I followed other sites guides on how to get bootstrap/jquery working with webpack and rails 5.2/6, but even though it does get them working. I do not see they ever confirm that jquery also works in their ajax.
Examples of the guides:
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