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

@gramex/filters

v2.0.0

Published

Populate filter inputs/dropdowns from data

Downloads

6

Readme

@gramex/filters

filters renders data as filters using <select> / <input> elements, or frameworks like Bootstrap, bootstrap-select, etc.

Sample usage:

gramex.filters.render({
  container: "form",
  data: {
    city: [
      { label: "London", value: "LON" },
      { label: "Oslo", value: "OSL" },
      { label: "Paris", value: "PAR" },
    ],
    channel: [
      { label: "Direct", value: "DIR" },
      { label: "Indirect", value: "IND" },
    ],
  },
});

Installation

Run npm install @gramex/filters

To use filters on the browser, include the script in your HTML:

<script src="https://cdn.jsdelivr.net/npm/@gramex/filters/filters.min.js"></script>
<!-- OR src="node_modules/@gramex/filters/filters.min.js"></script -->
<script>
  gramex.filters.render({...})
</script>

For use with ES6 modules, use:

<script type="module">
  import { render } from "node_modules/@gramex/filters/filters.js"
  //  OR { render } from "https://cdn.skypack.dev/@gramex/filters"
  //  OR { render } from "https://esm.sh/@gramex/filters"
  render({...})
</script>

Usage

<form id="basic-usage"></form>
<script type="module">
  import { render } from "node_modules/@gramex/filters/filters.js";
  render({
    container: "form#basic-usage",
    data: {
      product: ["Alpha", "Beta", "Gamma"],
      city: ["London", "Oslo", "Paris"],
      channel: ["Direct", "Indirect"],
    },
  });
</script>

This renders:

3 fields: product, city, channel

<form id="basic-usage">
  <select name="product">
    <option value="Alpha">Alpha</option>
    <option value="Beta">Beta</option>
    <option value="Gamma">Gamma</option>
  </select>
  <select name="city">
    <option value="London">London</option>
    <option value="Oslo">Oslo</option>
    <option value="Paris">Paris</option>
  </select>
  <select name="channel">
    <option value="Direct">Direct</option>
    <option value="Indirect">Indirect</option>
  </select>
</form>

Options

  • container: CSS selector or Element into which filter is rendered
  • type: type of HTML to generate. Can be
    • select: renders <select> and <option> elements in a HTML form
    • bs5: renders Bootstrap 5 dropdowns
    • bootstrap-select
    • select2
    • selectize
  • data: object with filter data. Keys are the filter names. Values are arrays of filter values.
    • Filter values can be a string: {"choice": ["X", "Y", "Z"]}
    • Filter values can be an object: {"choice": [{label: "X", value: "x"}, {label: "Y", value: "y"}]}
    • Filter names (like choice) map to field names (like <select name="choice">)
  • url: a URL that returns the data above.
    • At least one of data or url is required
    • data overrides url
    • If url is used, gramex.filters.render() returns a Promise that resolves to the JSON response of url
  • field: filter-specific field attributes. Keys are the filter names. Values are field attribute scalars or functions
    • {"city": {"multiple": true}, "product": {"multiple": false}} makes the city filter a multiple-select, but not product
    • {"city": {"class": "form-select"}} adds a class="form-select" to the city select
  • fields: common field attributes
    • {"multiple": true} makes all filters multiple-selects
    • {"class": "form-select"} adds a class="form-select" to all selects
  • value: filter-specific value attributes. Keys are the filter names. Values are value attribute scalars or functions
    • {"city": {"class": "small"}} adds class="small" to all options in the city filter
  • values: common value attributes
    • {"class": "small"} adds class="small" to all options in all filters

Depending on the type, field and value attributes are treated specially, as below.

type="select"

field/fields attributes:

  • name: sets <select name="${name}">. E.g. name: "city"
  • value: currently selected value. Sets selected attribute on matching items. E.g. value: "LON"
  • label: sets <label>${label} ...</label>. E.g. label: "City"
  • default: a value object to use as default, if it's missing in values. E.g. default: "-" or default: {label: "All", value: ""}
  • multiple: true: sets multiple on <select>. E.g. multiple: true
  • values: list of values to render as options. Defaults to data[name]
  • selector: renders existing <select> elements if found. E.g. selector: "select[data-name="${name}]" renders matching <select data-name="..."> if they exist, else creates new ones
  • render: function to render HTML if no <select> is found. Defaults roughly to ({label, name}) => `<label>${label} <select name="${name}"></select></label>`;

value/values attributes:

  • value: sets <option value="${value}">
  • label: sets <option>${label}</option>. Defaults to value
  • render: function to render HTML if no <option> is found. Defaults roughly to ({label, value}) => `<option value="${value}">${label}</option>`;

type="bs5"

field/fields attributes:

  • name: sets <div class="dropdown ${name}">. E.g. name: "city"
  • value: currently selected value. Sets class="active" on matching items. E.g. value: "LON"
  • label: sets <button>${label}</button>. Defaults to name. E.g. label: "City"
  • multiple: TODO: not implemented yet
  • default: a value object to use as default, if it's missing in values E.g. default: "-" or default: {label: "All", value: ""}
  • buttonClass: sets <button class="dropdown-toggle ${buttonClass}">
  • dropdownClass: sets <div class="dropdown ${dropdownClass}">
  • menuClass: sets <ul class="dropdown-menu ${menuClass}"></ul>
  • values: list of values to render as options. Defaults to data[name]
  • selector: renders existing .dropdown elements if found.
  • render: function to render HTML if no .dropdown is found

value/values attributes:

  • value: sets active class on .dropdown-item if value matches the current value
  • label: sets <li><a class="dropdown-item"}>${label}</a></li>. Defaults to value
  • render: function to render HTML if no <option> is found. Defaults roughly to ({label}) => <li><a class="dropdown-item">${label}</a></li>

Examples

Fetch data from URL

This loads data from data-sales.json and renders it as filters into the <form>.

<form></form>
<script type="module">
  import { render } from "node_modules/@gramex/filters/filters.js";
  render({
    container: "form",
    url: "data-sales.json",
  });
</script>

Sample data-sales.json:

{
  "product": ["Alpha", "Beta", "Gamma"],
  "city": ["London", "Oslo", "Paris"],
  "channel": ["Direct", "Indirect"]
}

This renders:

3 fields: product, city, channel

Add classes to field

Add fields.class to specify classes for all fields:

<link
  href="https://cdn.jsdelivr.net/npm/bootstrap@5/dist/css/bootstrap.min.css"
  rel="stylesheet"
/>
<form class="d-flex"></form>
<script type="module">
  import { render } from "node_modules/@gramex/filters/filters.js";
  render({
    container: "form",
    url: "data-sales.json",
    fields: { class: "form-select me-2" },
  });
</script>

This renders:

3 fields with Bootstrap classes added

Use existing HTML

To apply the filters to existing (styled) HTML, the <select> elements should have a name=, class= or id= that matches the field name.

<link
  href="https://cdn.jsdelivr.net/npm/bootstrap@5/dist/css/bootstrap.min.css"
  rel="stylesheet"
/>
<form class="row">
  <div class="col"><select name="city" class="form-select"></select></div>
  <div class="col"><select name="product" class="form-select"></select></div>
  <div class="col"><select name="channel" class="form-select"></select></div>
</form>
<script type="module">
  import { render } from "node_modules/@gramex/filters/filters.js";
  render({
    container: "form",
    url: "data-sales.json",
  });
</script>

This re-uses the existing <select> elements in the same order and style as in the HTML:

3 fields, re-using the existing HTML elements

Set selected values

Add fields.value to set selected values:

<form class="d-flex"></form>
<script type="module">
  import { render } from "node_modules/@gramex/filters/filters.js";
  render({
    container: "form",
    url: "data-sales.json",
    fields: { value: { product: "Beta", city: "Oslo", channel: "Direct" } },
  });
</script>

This renders:

3 fields with specified values selected

Set custom labels

Add value.[name].label to set custom labels:

<form></form>
<script type="module">
  import { render } from "node_modules/@gramex/filters/filters.js";
  const productDetails = {
    Alpha: "Version Alpha: $100",
    Beta: "Version Beta: $400",
    Gamma: "Version Gamma: $1,000",
  };
  render({
    container: "form",
    url: "data-sales.json",
    value: {
      product: { label: ({ value }) => productDetails[value] },
    },
  });
</script>

This renders:

Product values replaced by custom labels

Add default value

Add fields.default.[name] to add a default value:

<form></form>
<script type="module">
  import { render } from "node_modules/@gramex/filters/filters.js";
  render({
    container: "form",
    url: "data-sales.json",
    fields: {
      default: {
        product: { label: "Any product", value: "" },
        city: { label: "Any city", value: "" },
        channel: { label: "Any channel", value: "" },
      },
    },
  });
</script>

This renders:

Default values added to each field