Using Rails-UJS in JS modules (Rails 6 with webpacker)

◇◆丶佛笑我妖孽 提交于 2019-11-27 16:03:38

问题


i just switched to Rails 6 (6.0.0.rc1) which uses the Webpacker gem by default for Javascript assets together with Rails-UJS. I want to use Rails UJS in some of my modules in order to submit forms from a function with:

const form = document.querySelector("form")
Rails.fire(form, "submit")

In former Rails versions with Webpacker installed, the Rails reference seemed to be "globally" available in my modules, but now i get this when calling Rails.fire

ReferenceError: Rails is not defined

How can i make Rails from @rails/ujs available to a specific or to all of my modules?

Below my setup…

app/javascript/controllers/form_controller.js

import { Controller } from "stimulus"

export default class extends Controller {
  // ...
  submit() {
    const form = this.element
    Rails.fire(form, "submit")
  }
  // ...
}

app/javascript/controllers.js

// Load all the controllers within this directory and all subdirectories. 
// Controller files must be named *_controller.js.

import { Application } from "stimulus"
import { definitionsFromContext } from "stimulus/webpack-helpers"

const application = Application.start()
const context = require.context("controllers", true, /_controller\.js$/)
application.load(definitionsFromContext(context))

app/javascript/packs/application.js

require("@rails/ujs").start()
import "controllers"

Thanks!


回答1:


in my app/javascript/packs/application.js:

import Rails from '@rails/ujs';
Rails.start();

and then in whatever module, controller, component I'm writing:

import Rails from '@rails/ujs';



回答2:


Just add it to your environment.js file, here is mine (with bootstrap and jquery):

const {environment} = require('@rails/webpacker')
const webpack = require('webpack')

module.exports = environment

environment.plugins.prepend(
    'Provide',
    new webpack.ProvidePlugin({
        $: 'jquery',
        jQuery: 'jquery',
        jquery: 'jquery',
        'window.jQuery': 'jquery',
        "window.$": "jquery",
        Popper: ['popper.js', 'default'],
        Rails: ['@rails/ujs']
    })
)



回答3:


I am currently messing around on 6.0.0.rc2 but I think I got an answer for you.

So if you separate out the:

app/javascript/packs/application.js

require("@rails/ujs").start()
import "controllers"

To instead:

export const rails_ujs = require("@rails/ujs")
console.log(rails_ujs)
rails_ujs.start()

You can obviously remove that console.log was just trying to figure things out. Then in your stimulus controller you can simply do:

// Visit The Stimulus Handbook for more details
// https://stimulusjs.org/handbook/introduction
//
// This example controller works with specially annotated HTML like:
//
// <div data-controller="hello">
//   <h1 data-target="hello.output"></h1>
// </div>

import { Controller } from "stimulus"
import { rails_ujs } from "packs/application.js"

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

  connect() {
    // this.outputTarget.textContent = 'Hello, Stimulus!'
    console.log('hi')
    console.log(rails_ujs)
  }
}

Just using their little test controller here but I got it to console.log out and you can call rails_ujs.fire so that should be what you want :)

Let me know if this works for you!




回答4:


First at all, using yarn add rails/ujs:

yarn add  @rails/ujs

And add to config/webpack/environment.js

const webpack = require('webpack')
environment.plugins.prepend('Provide',
  new webpack.ProvidePlugin({
    $: 'jquery',
    jQuery: 'jquery',
    Popper: ['popper.js', 'default'],
    toastr: 'toastr/toastr',
    ApexCharts: ['apexcharts', 'default'],
    underscore: ['underscore', 'm'],
    Rails: ['@rails/ujs']
  })
)
module.exports = environment

Config and load Rails js.

# pack/application.js
require("@rails/ujs").start()
global.Rails = Rails;

And Then: This is result ->




回答5:


I think the best way is to use the expose-loader and configure it the same way webpacker would if you ran bundle exec rails webpacker:install:erb.


Install the expose-loader

$ yarn add expose-loader

Create a config file

  1. For loaders webpacker configures itself, it'll dump a config object in config/webpack/loaders. Create that folder if it doesn't exist.
  2. Create a file called config/webpack/loaders/expose.js
  3. Add this to that file:

    module.exports = {
      test: require.resolve('@rails/ujs'),
      use: [{
        loader: 'expose-loader',
        options: 'Rails'
       }]
    }
    

Add that loader to environment.js

Add these two lines to config/webpack/environment.js:

const expose = require('./loaders/expose')
environment.loaders.prepend('expose', expose)

The full file should look something like:

const { environment } = require('@rails/webpacker')
const expose = require('./loaders/expose')

environment.loaders.prepend('expose', expose)
module.exports = environment

That should give you access to the Rails object globally again.



来源:https://stackoverflow.com/questions/56128114/using-rails-ujs-in-js-modules-rails-6-with-webpacker

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!