3

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.

Chris Valentine
  • 1,405
  • 1
  • 17
  • 35

2 Answers2

8

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:

Chris Valentine
  • 1,405
  • 1
  • 17
  • 35
-1

Mostly this error "$ not defined" comes with the unavailability of jquery library at the page we load. Please check the console network at browser Is the jquery library is loading or not?

Please add quotes to the element selector as below:

$('.linked-btn').on('ajax:success',funcion(){
Rosy
  • 1
  • 1