# Javascript Setup

# How does it work?

All the pagy*_js helpers render their component on the client side. The helper methods render just a minimal HTML tag that contains a data-pagy attribute.

Your app should serve or bundle a small javascript file that will take care of converting the data embedded in the data-pagy attribute and make it work in the browser.

# 1. Pick a Javascript File

  • ES6 module to use with webpacker, esbuild, parcel, etc.

pagy-module.js
pagy-module.js 5.16KB

pagy-module.d.ts
pagy-module.d.ts 106B

  • It's an IIFE file meant to be loaded as is, directly in your production pages and without any further processing
  • Minified (~2k) and polyfilled to work also with quite old browsers

pagy.js
pagy.js 1.85KB

Browser compatibility list:
  • and_chr 103
  • and_ff 101
  • and_qq 10.4
  • and_uc 12.12
  • android 103
  • chrome 103
  • chrome 102
  • chrome 101
  • edge 103
  • edge 102
  • firefox 102
  • firefox 101
  • firefox 91
  • ios_saf 15.5
  • ios_saf 15.4
  • ios_saf 15.2-15.3
  • ios_saf 14.5-14.8
  • ios_saf 14.0-14.4
  • ios_saf 12.2-12.5
  • kaios 2.5
  • op_mini all
  • op_mob 64
  • opera 87
  • opera 86
  • opera 85
  • safari 15.5

pagy-dev.js
pagy-dev.js 20.5KB

# 2. Configure

Depending on your environment you have a few ways of configuring your app:

# Rails with assets pipeline

In older versions of Rails, you can configure the app to look into the installed pagy gem javascript files:

pagy.rb (initializer)
Rails.application.config.assets.paths << Pagy.root.join('javascripts') # uncomment.
manifest.js (or "application.js" for old sprocket sprockets):
//= require pagy
pagy.rb (initializer)
Rails.application.config.assets.paths << Pagy.root.join('javascripts') #uncomment
app/assets/config/manifest.js
//= link pagy-module.js
config/importmap.rb
pin 'pagy-module'
pagy.rb (initializer)
Rails.application.config.assets.paths << Pagy.root.join('javascripts')
application.html.erb
<%= javascript_include_tag "pagy" %>

# Builders

In order to bundle the pagy-module.js your builder has to find it either with a link or local copy, or by looking into the pagy javascript path:

You can create a symlink or a copy of the pagy-module.js file (available in the pagy gem) into an app compiled dir and use it as a regular app file. That way any builder will pick it up. For example:

config/initializers/pagy.rb
# Create/refresh the `app/javascript/pagy-module.js` symlink/copy every time 
# the app restarts (unless in production), ensuring syncing when pagy is updated.
# Replace the FileUtils.ln_sf with FileUtils.cp if your OS doesn't support file linking. 
FileUtils.ln_sf(Pagy.root.join('javascripts', 'pagy-module.js'), Rails.root.join('app', 'javascript')) \
unless Rails.env.production?

Prepend the NODE_PATH environment variable to the scripts.build command:

package.json
{
    "build": "NODE_PATH=\"$(bundle show 'pagy')/javascripts\" <your original command>"
}

Prepend the NODE_PATH environment variable to the scripts.build command:

package.json
{
    "build": "NODE_PATH=\"$(bundle show 'pagy')/javascripts\" <your original command>"
}
webpack.confg.js
module.exports = {
  ...,                          // your original config
  resolve: {                    // add resolve.modules
    modules: [
      "node_modules",           // node_modules dir
      process.env.PAGY_PATH     // pagy dir
    ]
  }
}

# Legacy way

Ensure that the erb loader is installed:

bundle exec rails webpacker:install:erb

Generate a local pagy javascript file using erb with webpacker:

app/javascript/packs/pagy.js.erb
<%= Pagy.root.join('javascripts', 'pagy.js').read %>
window.addEventListener(YOUR_EVENT_LISTENER, Pagy.init)

where YOUR_EVENT_LISTENER is the load event that works with your app ( e.g. "turbo:load", "turbolinks:load", "load", ...).

app/javascript/application.js
import './pagy.js.erb'

Prepend the NODE_PATH environment variable to the scripts.build command:

package.json
{
    "build": "NODE_PATH=\"$(bundle show 'pagy')/javascripts\" <your original command>"
}

Configure the plugins[resolve]:

rollup.confg.js
export default {
  ...,                                    // your original config
  plugins: [
    resolve({
              moduleDirectories: [        // add moduleDirectories
                "node_modules",           // node_modules dir
                process.env.PAGY_PATH     // pagy dir
              ]
            })
  ]
}

# Non-Rails apps

  • Just ensure Pagy.root.join('javascripts', 'pagy.js') is served with the page.

# 3. Initialize Pagy

After the helper is loaded you have to initialize Pagy to make it work:

pagy_initializer_controller.js
import {Controller} from "@hotwired/stimulus"
import Pagy from "pagy-module"  // if using sprockets, you can remove above line, but make sure you have the appropriate directive if your manifest.js file.

export default class extends Controller {
  connect() {
    Pagy.init(this.element)
  }
}
View
<div data-controller="pagy-initializer">
  <%== pagy_nav_js(@pagy) %>
</div>

Import and use the pagy module:

app/javascript/application.js
import Pagy from "pagy-module";

window.addEventListener("turbo:load", Pagy.init);
// if you choose pagy-module.js 
import Pagy from "pagy-module"

// plain javascript
window.addEventListener("load", Pagy.init)

// Turbo
window.addEventListener("turbo:load", Pagy.init)

// Turbolinks
window.addEventListener("turbolinks:load", Pagy.init)

// custom listener
window.addEventListener(yourEventListener, Pagy.init) 

# Caveats