npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

hotwire-virtualized

v0.0.7

Published

Virtualized lists for Hotwire

Downloads

6

Readme

Hotwire Virtualized

Virtualized lists for Hotwire using Stimulus and Turbo Streams.

hotwire-virtualized

Usage

A minimal example within a Rails app can be found here.

<div
  data-controller="virtualized"
  data-virtualized-row-height-value="50"
  data-virtualized-url-value="/load-items"
  data-virtualized-ids-value="[1,2,3,4,5]"
  style="height: 100vh"
>
  <template data-virtualized-target="placeholder">
    <li>Loading...</li>
  </template>

  <ul data-virtualized-target="content"></ul>
</div>

Turbo Actions

This library uses custom actions to interact with the virtualized list.

Replace / Load

<turbo-stream action="v-replace" target="1">
  <template>
    <li>ID {id}</li>
  </template>
</turbo-stream>

Remove

<turbo-stream action="v-remove" target="1"></turbo-stream>

Append

<turbo-stream action="v-append" target="6">
  <template>
    <li>ID 6</li>
  </template>
</turbo-stream>

Stimulus Actions

Prepend

<button
  data-action="virtualized#actionRender"
  data-virtualized-id-param="123"
  data-virtualized-action-param="prepend"
>
  Prepend ID
</button>

Append

<button
  data-action="virtualized#actionRender"
  data-virtualized-id-param="123"
  data-virtualized-action-param="append"
>
  Append ID
</button>

Emitting Events

Within a controller in your app, dispatch an event which includes:

  • id: The unique ID of this row, possibly to fetch from backend.
  • action: The action to perform, one of prepend, append, remove, before, after, replace.
  • element: The HTML element to be inserted, if left blank, virtualized will fetch from backend using id.
  • targetId: When action is "before" or "after" or "replace" used to place relative to another row.
  • virtualizedId: When multiple virtualized controllers are on the page, this is used to target a specific instance.
const { id, element } = this.buildElement();
this.dispatch("emit", {
  detail: { id, element, action: "append", scrollTo: true },
});

Catch the event and forward it to the virtualized controller's eventRender action:

<div
  data-controller="event"
  data-action="event:emit->virtualized#eventRender"
></div>

Actions

Modifying Rows

The actionRender action can be called to prepend, append, insert, remove, etc... rows.

Require params:

  • id: The unique ID of this row, possibly to fetch from backend.
  • action: What action to perform
    • prepend
    • append
    • after
    • before
    • replace
    • remove
  • targetId: when the action is relative
  • selector: used to find element to add to cache via document.querySelector(selector)

Preload Data

By default, the virtualized controller will fetch data from the backend for any IDs that aren't in its row cache. You can preload data into the row cache using the preloaded target. This is useful when you want to render the first set of rows immediately.

You must pass a data attribute of data-preloaded-id="1" where 1 is the ID that corresponds to the row, as it is how we correspond this row to the data in the row cache.

<template data-virtualized-target="preloaded" data-preloaded-id="1">
  <li>Preloaded 1</li>
</template>

<template data-virtualized-target="preloaded" data-preloaded-id="2">
  <li>Preloaded 2</li>
</template>

Multiple Virtualized

When you require multiple instances on a single page, you must set the virtualized-id value to a unique value for each instance. The default value when not set is virtualized.

<div
  data-controller="virtualized"
  data-virtualized-virtualized-id-value="virtual-a"
>
  <!-- First Instance -->
</div>

<div
  data-controller="virtualized"
  data-virtualized-virtualized-id-value="virtual-b"
>
  <!-- Second Instance -->
</div>

Stream Responses

When stream responses need to target a specific instance must include the virtualized-id attribute:

<turbo-stream action="v-replace" target="1" virtualized-id="virtual-a">
  <template>
    <li>Content</li>
  </template>
</turbo-stream>

Events

Events can also be targeted towards a specific instance using the virtualizedId detail value:

this.dispatch("emit", {
  detail: { id, element, action: "prepend", virtualizedId: "virtual-a" },
});

Request Headers

Requests to load data from the server will include the X-Virtualized-Id header value in order to differentiate requests being made by different instances.

Scrolling

You can call the scrollTop or scrollBottom actions to scroll to the top or bottom of the list.

<button data-action="virtualized#scrollTop">Scroll Top</button>
<button data-action="virtualized#scrollBottom">Scroll Bottom</button>