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 🙏

© 2026 – Pkg Stats / Ryan Hefner

nestedy

v1.1.0

Published

A Nested Fields Creator

Readme

Nestedy - A Nested Fields Creator.

Tests NPM Version Maintainability Sponsor

If you're migrating from v0 to v1 check the Upgrade document.

Nested Attributes for Rails?

Nestedy plays nice with accepts_nested_attributes_for using the destroy option.

Usage

<script src="nestedy.js"></script>

<form>
  <div class="nestedy">
    <div class="nestedy-item">
      <input id="some_0_value" name="some[0][value]">

      <i class="nestedy-remove"></i>
    </div>
  </div>

  <i class="nestedy-add"></i>
</form>
const nestedy = new Nestedy(document.querySelector('form'));

nestedy.init();

By default Nestedy will look for an id and name as Rails style, where the dynamic part of the id is the number _0_ and the dynamic part of the name is the number [0].

Usage with Template

When the model lives outside the form, use the template option with an HTML <template> element. It receives a selector and the matched element is cloned into the .nestedy wrapper.

<script src="nestedy.js"></script>

<template id="template">
  <div class="nestedy-item">
    <input id="some_0_value" name="some[0][value]">
    <i class="nestedy-remove"></i>
  </div>
</template>

<form>
  <div class="nestedy"></div>

  <i class="nestedy-add"></i>
</form>
new Nestedy(document.querySelector('form'), { template: '#template' }).init();

Options

| Property | Default | Description | |----------------|------------------------------------|--------------------------------------------------------------------------------------------------------------------| |add |undefined |Callback triggered when the add button is clicked. Runs with the instance as this and receives (item, element). | |addButton |'.nestedy-add' |The add button element. | |change |undefined |Callback triggered after an item is added or removed. Runs with the instance as this and receives (count, item, element). | |checkable |['checkbox', 'radio'] |The checkable fields. These fields will be unchecked on clone. | |clear |':input' |The fields to be cleared. A selector or a callback that receives each field and returns a boolean. | |content |'.nestedy' |Place where the items will be copied. | |destroy |false |If true, hides the item and adds a hidden _destroy field set to true instead of removing it. | |destroyex |/(\[)[^\[]*(\])$/ |Regex used to find the part of the field name that will be replaced by _destroy. | |excludes |undefined |Selectors (array) or a callback that receives each field, used to exclude fields before cloning. | |focus |':last' |The item you want to focus. Choose :first, :last or false to disable. | |idx |/(_)\d(_)/ |Regex used to find the dynamic part of the id of the field that will be changed. | |model |'.nestedy-item' |The element inside the content that will be used as a model to be cloned. | |namex |/(\[)\d(\])/ |Regex used to find the dynamic part of the name of the field that will be changed. | |remove |undefined |Callback triggered before an item is removed. Runs with the instance as this and receives (item, element). | |removeButton |'.nestedy-remove' |The remove button element. | |selectable |['select-one', 'select-multiple'] |The selectable fields. These fields will have the first option selected on clone. | |template |undefined |An HTML <template> inside the body that will be used as a model to be cloned. | |typeful |['color', 'date', ..., 'week'] |The typeful fields. These fields will have the value cleared on clone. |

Functions

To call some function, first, save the Nestedy instance on a variable and then call the functions:

const nestedy = new Nestedy(document.querySelector('form')).init();

| Function | Description | |-------------------------|----------------------------------------| |nestedy.add() |Adds one item. | |nestedy.add(number) |Adds the given number of items. | |nestedy.remove() |Removes the last item. | |nestedy.remove('first')|Removes the first item. | |nestedy.remove('last') |Removes the last item. | |nestedy.remove(number) |Removes a specific item by its position.|

Callbacks

add, remove and change

The add and remove callbacks run with the Nestedy instance as this and receive (item, element):

Return false from add or remove to cancel the action.

The change callback runs after an item is added or removed with the Nestedy instance as this and (count, item, element):

new Nestedy(form, {
  add(item, element) {
    // item    → new .nestedy-item (clone)
    // element → the form
    // this    → Nestedy instance
  },
  remove(item, element) {
    // item    → .nestedy-item about to be removed
    // element → the form
    // this    → Nestedy instance
  },
  change(count, item, element) {
    // count   → number of visible items
    // item    → .nestedy-item added or removed
    // element → the form
    // this    → Nestedy instance
  }
}).init();

clear

When clear is a function, it receives each input inside the cloned item and returns a boolean. Return true to clear the field value.

new Nestedy(form, {
  clear(field) {
    // field → input, select, or textarea inside the cloned item
    return field.value !== 'ignore';
  }
}).init();

excludes

When excludes is a function, it receives each input inside the cloned item and returns a boolean. Return true to remove the field from the clone.

new Nestedy(form, {
  excludes(field) {
    // field → input, select, or textarea inside the cloned item
    return field.id.match(/product_prices_attributes_\d_name/);
  }
}).init();

Build

gulp 'amd'
gulp 'umd'
gulp 'commonjs'
gulp 'systemjs'
gulp 'es6'
gulp 'es5'
gulp 'es5-test'