Ruby on rails 在JS模块中使用Rails UJS(带webpacker的Rails 6)

Ruby on rails 在JS模块中使用Rails UJS(带webpacker的Rails 6),ruby-on-rails,webpack,webpacker,rails-ujs,Ruby On Rails,Webpack,Webpacker,Rails Ujs,我刚刚切换到Rails 6(6.0.0.rc1),默认情况下,它将gem与Rails UJS一起用于Javascript资产。我想在我的一些模块中使用Rails UJS,以便从具有以下功能的函数提交表单: const form = document.querySelector("form") Rails.fire(form, "submit") 在以前安装了Webpacker的Rails版本中,Rails引用似乎在我的模块中“全局”可用,但现在我在调用Rails.fire ReferenceE

我刚刚切换到Rails 6(6.0.0.rc1),默认情况下,它将gem与Rails UJS一起用于Javascript资产。我想在我的一些模块中使用Rails UJS,以便从具有以下功能的函数提交表单:

const form = document.querySelector("form")
Rails.fire(form, "submit")
在以前安装了Webpacker的Rails版本中,
Rails
引用似乎在我的模块中“全局”可用,但现在我在调用
Rails.fire

ReferenceError: Rails is not defined
如何使来自
@Rails/ujs的
Rails
可用于特定模块或我的所有模块?

在我的设置下面

app/javascript/controllers/form_controller.js

app/javascript/controllers.js

app/javascript/packs/application.js

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

谢谢

只需将其添加到您的environment.js文件中,这是我的(带有引导和jquery):


我目前正在6.0.0.rc2上胡闹,但我想我已经为您找到了答案

因此,如果您将以下各项分开:

app/javascript/packs/application.js

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

export const rails_ujs = require("@rails/ujs")
console.log(rails_ujs)
rails_ujs.start()
很明显,您可以删除console.log只是想弄清楚一些事情。 然后在刺激控制器中,您可以简单地执行以下操作:

// 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)
  }
}
//有关更多详细信息,请访问刺激手册
// https://stimulusjs.org/handbook/introduction
//
//此示例控制器适用于特殊注释的HTML,如:
//
// 
//   
// 
从“刺激”导入{Controller}
从“packs/application.js”导入{rails_ujs}
导出默认类扩展控制器{
静态目标=[“输出”]
连接(){
//this.outputTarget.textContent='你好,刺激!'
console.log('hi')
log(rails\u ujs)
}
}
只是在这里使用他们的小测试控制器,但我把它放到了console.log out中,您可以调用
rails\u ujs.fire
所以这应该是您想要的:)


让我知道这是否适合你

在我的
app/javascript/packs/application.js
中:

import Rails from '@rails/ujs';
Rails.start();
然后在我写的任何模块、控制器和组件中:

import Rails from '@rails/ujs';

我认为最好的方法是使用,并按照运行bundle exec rails webpacker:install:erb
时webpacker的配置方式对其进行配置


安装
公开加载程序
创建一个配置文件
  • 对于加载程序webpack自行配置,它将在
    config/webpack/loaders
    中转储配置对象。如果该文件夹不存在,请创建该文件夹

  • 创建一个名为
    config/webpack/loaders/expose.js的文件

  • 将以下内容添加到该文件:

    module.exports={
    测试:require.resolve(“@rails/ujs”),
    使用:[{
    加载器:“公开加载器”,
    选项:“Rails”
    }]
    }
    //更高版本的expose loader可能允许以下API:
    module.exports={
    测试:require.resolve(“@rails/ujs”),
    加载器:“公开加载器”,
    选项:{公开:“Rails”}
    }
    
  • 将该加载程序添加到
    environment.js
    将这两行添加到
    config/webpack/environment.js

    import Rails from '@rails/ujs';
    Rails.start();
    
    const expose=require(“./loaders/expose”)
    environment.loaders.prepend('expose',expose)
    
    完整文件应类似于:

    const{environment}=require(“@rails/webpacker”)
    const expose=require(“./loaders/expose”)
    environment.loaders.prepend('expose',expose)
    module.exports=环境
    

    这将使您能够再次全局访问
    Rails
    对象。

    首先,使用添加Rails/ujs:

    yarn add  @rails/ujs
    
    并添加到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
    
    配置并加载Rails js

    # pack/application.js
    require("@rails/ujs").start()
    global.Rails = Rails;
    
    然后: 这是结果->

    我就是这么做的。网页包TS2304:找不到名称“Rails”
    。您是否也通过package.json添加了它?npm添加@rails/ujsI道歉。让我澄清一下。我可以导入这个包,但是使用全局变量
    Rails
    gives
    TS2304:找不到名称“Rails”
    。请查看它以获取javascript中的Rails实例@ThienSuBS这是一个-我花了几个星期寻找答案。非常感谢你的回答,它对我来说既简单又有效。我现在导入
    form_controller.js
    form a npm包,以便在多个rails应用程序中重用它。在不同的控制器上多次从“@Rails/ujs”导入Rails有什么不利之处吗?如果不是的话,我会把这个标记为公认的答案。没有缺点——事实上,我会说这正是我们在模块化ES6世界中应该如何声明每个文件的依赖关系。无论导入多少次,Webpack都将只加载一次
    @rails/ujs
    。每个控制器只获得相同的导出
    Rails
    ,即使您使用不同的名称导入它,或者存在公共的js
    require()
    而不是ES6
    import
    ,这仍然是正确的。请注意只调用
    .start()
    一次,可能是在您的
    应用程序.js
    中。我会看到@ThienSuBS的答案并阅读此处的文档:。我也有同样的问题;我不想在我使用的每个文件中导入Rails,而webpack插件支持正是针对这种情况构建的:“自动加载模块,而不必到处导入或需要它们。”@Dan L:依赖globals是最臭名昭著的编程反模式之一,所以不,我不支持ProvidePlugin,而是特别支持导入依赖项。首先,编写依赖于全局运行时状态的模块是人们最终陷入这种混乱状态的原因。更重要的是,问题在于编写模块。依赖于全局状态的模块不是。。。伊诺皮纳图斯:我理解世界各地对全球化的关注,并普遍同意这一点。我对
    Rails
    特别是在全局空间中很满意,因为它是一个实用程序库,它抽象了我想要一直使用的公共特性(比如AJAX请求)。我认为它类似于jQuery;我不想在每个JS文件上导入jQuery,因为jQuery是我用来构建真正的应用程序c的工具
    yarn add  @rails/ujs
    
    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
    
    # pack/application.js
    require("@rails/ujs").start()
    global.Rails = Rails;