Rails 6 use Webpacker javascript functions in rails view

Viewed 608

I'd like to reuse a javascript function I wrote in several different views. How can I go about doing this in rails 6? The only solution I've been able to use so far is defining the function in a javascript file as window.functionName = function() {}

However many other posts about this say it's a bad solution and should be avoided. What's the proper way to define functions that I can use in my rails views?

1 Answers

If you're using Webpacker, I recommend exporting your JavaScript application as a library.

First, export any references you'd like to access from your view. These references must be exported from the entrypoint to your Webpacker code, usually the application.js file, i.e. app/javascript/packs/application.js (Webpacker 5) or app/packs/entrypoints/application.js (Webpacker 6).

// app/javascript/packs/application.js

import { functionName } from '../src/functionName'

export functionName // <== we want this function to be available in the view

In your Webpacker config, you would add this snippet to indicate you want to treat your JavaScript code as a library.

Webpacker 5

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

environment.config.merge({
  output: {
    // Choose whatever you want for `library`, [name] is a placeholder
    library: ['Packs', '[name]'],

    // Attach the library to the global scope in the browser
    libraryTarget: 'window'
  },
})

module.exports

Webpacker 6

// config/webpack/base.js

const { webpackConfig, merge } = require('@rails/webpacker')

module.exports = merge(webpackConfig, {
  output: {
    // Makes exports from entry packs available to global scope, e.g.
    library: ['Packs', '[name]'],
    libraryTarget: 'window'
  },
})

With the above configuration, webpack will export a module called Packs to the global scope. The Packs variable will have a property corresponding to each entry by [name]. For the entrypoint named application.js, then you would access your function as a property of Packs.application in your view.

Example:

<%= javascript_pack_tag 'application' %>
<script>
Packs.application.functionName()
</script>
Related