StimulusJS с Turbolinks, должны ждать события "turbolinks: load" для запуска контроллеров StimulusJS - PullRequest
1 голос
/ 10 июля 2019

У меня есть довольно стандартное приложение на Rails 5.2 (соответствует практически всем соглашениям), использующее пряжу и веб-упаковщик, с версией стимула 1.1.1 в моем файле package.json и yarn.lock.

# package.json
{
  "name": "MY_APP_NAME",
  "private": true,
  "dependencies": {
    "@rails/webpacker": "^4.0.2",
    "coffeescript": "1.12.7",
    "stimulus": "^1.1.1"
  },
  "devDependencies": {
    "webpack-dev-server": "^3.2.1"
  }
}

FromНа странице StimulusJS Discourse (https://discourse.stimulusjs.org/t/stimulusjs-and-turbolinks/669), начиная со Stimulus 1.1, контроллеры стимулов выполняют методы подключения / инициализации после того, как DOM готов с турболинками.

Однако единственным способом, которым я мог заставить приведенный ниже контроллервыполнить правильно - добавить обработчик события, чтобы дождаться, пока не сработает событие turbolinks:load.

Если это важная информация, я пытаюсь использовать плагин jQuery Select2 для создания настраиваемого элемента select.

# app/javascript/packs/controllers/intake_customization_controller.js
import { Controller } from "stimulus";

export default class extends Controller {
  static targets = [ "userIds" ]

  initialize() {
    // Code will not execute without this event handler wrapping it...
    $(document).on("turbolinks:load", ()=> {
      $(this.userIdsTarget).select2()
    })
  }
}

HTML-форма:

<%= form_with model: @account, url: settings_intake_customization_path, method: :put, id: "settings-intake_customization-form", data: { controller: "intake-customization" } do |form| %>
  <%= form.collection_select :user_ids, current_account.users, :id, :name, { include_blank: false }, { multiple: true, data: { target: "intake-customization.userIds" } } %>
<% end %>

Я что-то упустил при настройке контроллера стимула с турболинками?

Используя обработчик событий turbolinks:load, я могу получить функциональностьЯ хочу, но из того, что я прочитал на форуме Discourse, мне не нужно было использовать обработчик событий.

Возможно ли, что мое приложение "кэшировало" более старую версию Sтимулус, хотя package.json говорит иначе?

1 Ответ

0 голосов
/ 12 июля 2019

Насколько я понимаю, Stimulus был разработан для работы с Turbolinks. Я был бы удивлен, если бы вам нужно было обернуть ваш код внутри обработчика событий для turbolinks:load. Возможно, вы хотите использовать событие connect вместо события initialize, потому что событие initialize срабатывает при первом создании контроллера. Событие connect срабатывает каждый раз, когда контроллер подключается к DOM.

Из документов для обратного вызова жизненного цикла connection говорится:

Контроллер подключается к документу, если выполняются оба следующих условия:

  • его элемент присутствует в документе (то есть, потомок document.documentElement, элемент)
  • его идентификатор присутствует в атрибуте data-controller элемента

Когда контроллер подключается, Stimulus вызывает его метод connect ().

Поскольку вы хотите манипулировать DOM с помощью jQuery Select2, обратный вызов жизненного цикла connect кажется мне более подходящим. Я проведу еще несколько исследований, но думаю, что событие initialize вызывается всякий раз, когда код для контроллера загружается в браузер. Если это так, то существует вероятность того, что событие initialize будет запущено до того, как часть дерева DOM, использующая ваш контроллер (и элемент DOM, который вы пытаетесь запросить), сможет отрендерить:

# app/javascript/packs/controllers/intake_customization_controller.js

import { Controller } from "stimulus";

export default class extends Controller {
  static targets = [ "userIds" ]

  connect() {
    $(this.userIdsTarget).select2()
  }
}

Мне удалось найти статью , в которой сказано использовать connect вместо turbolinks:load. Эта статья написана кем-то, кто опубликовал несколько учебных пособий по стимулам , поэтому он выглядит довольно уважаемым. У меня проблемы с поиском чего-либо, что подробно описывает различия между initialize и connect, за исключением того, что initialize запускается один раз и connect запускается каждый раз, когда он подключается к DOM. Для того, чтобы событие connect было запущено снова, должно быть событие disconnected, запущенное между

...