Попытка использовать 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()