'How to use jqueryUI in a rails 6 or rails 7 alpha engine

I would be grateful if someone could show the exact steps needed to use jquery ui in a rails 6 or rails 7 Alpha 2 engine. I have been unable to get either importmap-rails to work in a rails 7 engine nor can I get webpacker to work in a Rails 6 engine or rails 7 alpha 2 engine. Given an engine called custom_page generated using

rails plugin new custom_page --mountable --full

I included the jquery-ui-rails in the gemspec as a dependency.

spec.add_dependency 'jquery-ui-rails'

Perhaps this should be a runtime_dependency? The full list of dependencies is

  spec.add_dependency "rails", "~> 7.0.0.alpha2"

  spec.add_dependency 'new_ckeditor'

  spec.add_dependency 'ancestry'
  spec.add_dependency 'friendly_id', '>= 5.4.0'
  spec.add_dependency 'pg_search'

  spec.add_dependency 'carrierwave', '~> 2.0'
  spec.add_dependency 'carrierwave-imageoptimizer'
  spec.add_dependency 'sassc-rails', '~> 2.0.0'
  spec.add_dependency 'pg', '~> 1.1'
  spec.add_dependency 'jquery-rails'
  spec.add_dependency 'jquery-ui-rails'

  spec.add_development_dependency "puma"

  #Testing Gems
  spec.add_development_dependency "rspec-rails", '>= 5.0'
  spec.add_development_dependency "factory_bot_rails"
  spec.add_development_dependency "guard-rspec"

  spec.add_development_dependency 'capybara', '>= 3.32'
  spec.add_development_dependency 'selenium-webdriver'
  spec.add_development_dependency 'launchy'
  spec.add_development_dependency 'database_cleaner-active_record'

I have required the same in the engine.rb

require 'jquery-ui-rails'
require 'friendly_id'
require 'ancestry'

    module CustomPage
      class Engine < ::Rails::Engine
        isolate_namespace CustomPage
    
        config.generators do |g|
          g.test_framework :rspec,
            fixtures: false,
            request: false,
            view_specs: false,
            helper_specs: false,
            controller_specs: false,
            routing_specs: false
          g.fixture_replacement :factory_bot
          g.factory_bot dir: 'spec/factories'
        end
      end
    end

I have added a simple test in a view

<p id="notice"><%= notice %></p>

<script type='text/javascript'>
  $(function() {
    $('.datepicker').datepicker();
  });
</script>

I have included the require in app/assets/stylesheets/custom_page/application.css

/*
 * This is a manifest file that'll be compiled into application.css, which will include all the files
 * listed below.
 *
 * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
 * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
 *
 * You're free to add application-wide styles to this file and they'll appear at the bottom of the
 * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
 * files in this directory. Styles in this file should be added after the last require_* statement.
 * It is generally better to create a new file per style scope.
 *
 *= require_tree .
 *= require_self
 */
 /*
  *= require jquery-ui
 */

And also in the app/assets/config/custom_page_manifest.js

//= link_directory ../stylesheets/custom_page .css
//= require jquery-ui

I get an error when inspecting the browser console in firefox showing

Uncaught ReferenceError: $ is not defined

I've obviously shown a Rails 7 alpha 2 example here, however the same issue occurs using rails 6.1.4

The purpose of this exercise is to enable me to use the jquery library jqtree which would be simple to setup if I were to be able to use importmap-rails, however, as per my open, as yet unanswered, question here, I am unable to do so.

So I'm really asking how to use jquery libraries in Rails 6.1.4 engines or in Rails 7 alpha 2 libraries



Solution 1:[1]

This wasn't as straightforward as I thought it would be. First of all, jquery-ui-rails and jquery-rails seem outdated. I don't think you should use those gems. We can use importmaps since we've set it up for the engine already. But the usage isn't limited to the engine.

# config/importmap.rb

# NOTE: pin jquery to jsdelivr. this will make jquery global on import;
#       jspm wraps packages in a module [1], so jquery is not available globally.
pin "jquery", to: "https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.js"

# NOTE: a few answers suggested `jquery-ui-dist`. I couldn't add it with 
#       `bin/importmap`; use https://generator.jspm.io/ to get the url.
pin "jquery-ui-dist", to: "https://ga.jspm.io/npm:[email protected]/jquery-ui.js"

# works fine
pin "jqtree", to: "https://ga.jspm.io/npm:[email protected]/lib/tree.jquery.js"

# [1] someone, please, link to/explain what jspm does exactly to cause this.
// app/javascript/application.js

import "jquery";
import "jquery-ui-dist";
import "jqtree";

console.log(window.$);   // jQuery is already global
console.log($.ui);       // jquery-ui initialized on import
console.log($().tree);   // jqtree also initialized

If you'd like to stick to jspm for some reason, dynamic import() can be used to load jquery plugins.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#dynamic_imports

# config/importmap.rb

pin "jquery", to: "https://ga.jspm.io/npm:[email protected]/dist/jquery.js"
pin "jquery-ui-dist", to: "https://ga.jspm.io/npm:[email protected]/jquery-ui.js"
pin "jqtree", to: "https://ga.jspm.io/npm:[email protected]/lib/tree.jquery.js"
// app/javascript/application.js

import jQuery from "jquery";

// NOTE: keep in mind, these will be lazily loaded; use first method if this 
//       doesn't work in your set up.
import("jquery-ui-dist");
import("jqtree");

console.log(window.$);      // undefined
console.log(window.jQuery); // undefined
console.log(jQuery().ui);   // undefined
console.log(jQuery().tree); // undefined

// NOTE: make jquery global
window.$ = window.jQuery = jQuery;

For rails 6 setup with jquery-ui-rails and jquery-rails gems. Make sure you require jquery as well. Don't touch manifest.js, you're not precompiling jquery, you're precompiling application.{css,js} which already includes jquery. You have to add require to application.js as well.

https://github.com/rails/jquery-rails#installation

https://github.com/jquery-ui-rails/jquery-ui-rails#require-everything

// app/assets/javascripts/application.js

//= require jquery
//= require jquery-ui
/* app/assets/stylesheets/application.css */

/*= require jquery-ui */

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1