Попытка использовать select2 с Importmaps на Rails 7

Я пытаюсь использовать Select2 в новом приложении Rails 7 и борюсь следующим образом:

Я прикрепил его к своим картам импорта и импортировал так:

      pin "application", preload: true
pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
pin_all_from "app/javascript/controllers", under: "controllers"
pin "trix"
pin "@rails/actiontext", to: "actiontext.js"
pin "select2", to: "https://ga.jspm.io/npm:select2@4.1.0-rc.0/dist/js/select2.js"
pin "jquery", to: "https://ga.jspm.io/npm:jquery@3.6.0/dist/jquery.js"

(две последние строки были добавлены, когда я запускаю bin/importmap pin select2)

      import "jquery";
import "select2";
import "@hotwired/turbo-rails";
import "controllers";
import "trix";
import "@rails/actiontext";

(переместили как jquery, так и select2 в конец, а также в начало - ничего не изменилось).

Когда я нахожусь в форме, я могу получить доступ к элементу с $ следующим образом:

      $('#book_genre_ids');
...(returns the element)

Но когда я вручную пытаюсь - в консоли - запустить select2() для элемента, вот что происходит:

      $('#book_genre_ids').select2();
VM574:1 Uncaught TypeError: $(...).select2 is not a function
    at <anonymous>:1:22

Я проверил сетевые источники (консоль Chrome) и смог найти npm: jquery@3.6.0 /dist и npm: select2@4.1.0-rc.0/dist из gap.jspm.io. Я нашел некоторые ресурсы, которые указывали на загрузку нескольких библиотек jquery, но я не нашел ничего, кроме вышеперечисленного, в сетевых источниках в консоли...

2 ответа

Select2 зарегистрирует себя как функцию jQuery. .select2(), поэтому для использования этого метода библиотека должна быть загружена после библиотеки, иначе она не сможет найти ссылку, следовательно, не сможет зарегистрировать функцию, отсюда и ошибка $(...).select2 is not a functionбудет кидать.

      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.min.js" />

Тем не менее importявляется асинхронной загрузкой, поэтому не гарантируется, что при поиске эта библиотека будет загружена. Поэтому, хотя вы настраиваете их импорт в следующем порядке:

      import "jquery";
import "select2";

До сих пор не найдено, когда это было необходимо.

К счастью, gem importmap-rails поддерживает предварительную загрузку пин-модулей (modulepreload), поэтому, основываясь на этом, я придумал решение: preload jqueryдо select2

      # config/importmap.rb
pin "jquery", to: "https://ga.jspm.io/npm:jquery@3.6.0/dist/jquery.js", preload: true
pin "select2", to: "https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"

Затем я следую способу настройки Rails7 "@hotwired/stimulus" для настройки "jquery"

      // app/javascript/controllers/application.js
import { Application } from "@hotwired/stimulus"
...
import jQuery from "jquery"
window.jQuery = jQuery // <- "select2" will check this
window.$ = jQuery
...

теперь на контроллерах стимулов, где требуется «select2», вы можете загрузить «select2»

      // app/javascript/controllers/demo_controller.js
import { Controller } from "@hotwired/stimulus"
import "select2"

export default class extends Controller {
  initialize() {
    $('.js-example-basic-multiple').select2();
  }
// ...

Примечание: ваш источник CDN "select2" "https://ga.jspm.io/npm: /dist/js/select2.js" содержит import e from"jquery";в первой строке, следовательно, это не будет работать в этом решении, поэтому я рекомендую использовать официальную ссылку cdn: «https://cdn.jsdelivr.net/npm/ [email protected][email protected] /dist/js/select2.min.js " вместо.

Обновить

Если вы не хотите использовать стимул, вы можете прикрепить другой файл js для настройки «select2» и загрузить его в свои макеты.

      // app/javascript/utils.js
import "select2"

$(document).ready(function () {
  $('.js-example-basic-multiple').select2();
});
      # config/importmap.rb
...
pin "utils"

# app/views/products/show.html.erb
<%= javascript_import_module_tag("utils") %>
...

Примечание: вы должны использовать javascript_import_module_tag, нет javascript_importmap_tags, ссылка

Спасибо Лам Фану. но этого не достаточно. Для меня загрузка select2 была решена просто, чего я и ожидал. Он разрешил инициализацию select2 как для среды разработки, так и для рабочей среды.

См. vendor/assets/javascriptsпапка внутри драгоценного камня select2-rails. В этой папке находится файл select2.js

Добавь в свой app/assets/config/manifest.jsстроки в таком порядке:

      //= link jquery.min.js
//= link select2.js

Мне этого достаточно и пины и импорт работают по умолчанию:

      # config/importmap.rb

pin 'jquery', to: 'jquery.min.js'
...
pin 'select2'
pin 'application'
pin_all_from 'app/javascript', under: 'application'
      // app/javascript/application.js
import 'jquery'
...
import 'select2'
      # app/views/layout/application.html.haml
...
  %head
    = javascript_importmap_tags 'application'
      // app/javascript/utils/select2_init.js
export class Select2Init {
  start() {
    $(function() {
      $('.select2').select2()
    })
  }
}

и запустите инициализатор в начальной точке:

      import { Select2Init } from 'application/utils/select2_init'

new Select2Init().start()
Другие вопросы по тегам