New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

dynamic_nested

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dynamic_nested - npm Package Compare versions

Comparing version 0.1.0 to 0.1.1

example.gif

51

index.js

@@ -17,4 +17,4 @@ /**

* <%= content_tag :div, dynamic_nested_index: c.index do %>
* # PS: generate hidden fields inside rows group to handle them easily.
* = for {key, value} <- row.hidden do
* # PS: generate hidden fields manually for handling them easily.
* = for {key, value} <- c.hidden do
* = hidden_input c, key, value: value, dynamic_nested_field_id: true

@@ -30,4 +30,4 @@ * <%= text_input c, :name %>

*
* Everytime a User adds a new row, it is going to generate a new index for that row incrementing
* +1 from the last row on the page. As soon as an User removes a row, all indexes will be updated
* Everytime a User adds a new nested, it is going to generate a new index for that nested incrementing
* +1 from the last nested on the page. As soon as an User removes one, all indexes will be updated
* accordingly to reflect their position on the page.

@@ -43,2 +43,16 @@ *

*
* It supports the following callbacks:
*
* * beforeClone - You might want to do something before cloning the element.
* * afterAdd - You might want to do something after adding the new element.
* * afterRemove - You might want to do something after removing the element.
*
* ```JS
* const beforeClone = (element) => { ... }
* const afterAdd = (element, newElement) => { ... }
* const afterRemove = (elements) => { ... }
*
* new DynamicNested(element, { beforeClone, afterAdd, afterRemove })
* ```
*
* ## Know caveats

@@ -49,7 +63,7 @@ *

* * You must be using the last version of `Phoenix.HTML` that supports `skip_hidden` fields.
* * There is no way to whether execute callbacks before/after cloning rows or removing them.
**/
class DynamicNested {
constructor(element) {
constructor(element, options = {}) {
this.element = element
this.options = options

@@ -92,3 +106,4 @@ this.toggleRemoveButtonDisplay()

// TODO: provide callback to do something before cloning nested.
if (this.options.beforeClone) { this.options.beforeClone($lastNested) }
const $newNested = $lastNested.cloneNode(true)

@@ -115,4 +130,4 @@

// When editing the form, the cloned row will have hidden ids. They must be removed from the new
// row.
// When editing the form, the cloned element will have hidden ids. They must be removed from
// the new element.
const hiddenId = $newNested.querySelector('[dynamic-nested-field-id]')

@@ -125,6 +140,6 @@ if (hiddenId) { $newNested.removeChild(hiddenId) }

// Add new row on the page.
// Add new nested on the page.
this.element.appendChild($newNested)
// TODO: provide callback to something after adding new nested on the page.
if (this.options.afterAdd) { this.options.afterAdd($lastNested, $newNested) }
}

@@ -139,9 +154,9 @@

this.replaceIndex($nested, index)
})
// TODO: provide callback to something after removing nested on the page.
})
if (this.options.afterRemove) { this.options.afterRemove($allNested) }
}
/**
* Replace indexes in `id`, `name` and `for` for all children from the given row element.
* Replace indexes in `id`, `name` and `for` for all children from the given nested element.
*

@@ -188,7 +203,7 @@ * @param {object} element - DOM element.

*
* newAttributeName(<input name="invoice[invoice_rows][0][amount]">, "name", 1)
* => "invoice[invoice_rows][1][amount]"
* newAttributeName(<input name="user[categories][0][name]">, "name", 1)
* => "user[categories][1][name]"
*
* newAttributeName(<input id="invoice_invoice_rows_0">, "id", 1)
* => "invoice_invoice_rows_1"
* newAttributeName(<input id="user_categories_0">, "id", 1)
* => "user_categories_1"
**/

@@ -195,0 +210,0 @@ newAttributeName(element, attribute, index) {

{
"name": "dynamic_nested",
"version": "0.1.0",
"version": "0.1.1",
"description": "Add/Remove nested associations dynamically in forms that generates markup like Phoenix Framework.",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -5,2 +5,4 @@ # Dynamic Nested

![](example.gif)
## Examples

@@ -41,2 +43,18 @@

It supports the following callbacks:
* beforeClone - You might want to do something before cloning the element.
* afterAdd - You might want to do something after adding the new element.
* afterRemove - You might want to do something after removing the element.
```JS
const beforeClone = (element) => { ... }
const afterAdd = (element, newElement) => { ... }
const afterRemove = (elements) => { ... }
document
.querySelectorAll('[dynamic-nested]')
.forEach(element => DynamicNested(element, { beforeClone, afterAdd, afterRemove }))
```
Everytime a User adds a new row, it is going to generate a new index for that row incrementing

@@ -43,0 +61,0 @@ +1 from the last row on the page. As soon as an User removes a row, all indexes will be updated

import DynamicNested from '../index'
import '@testing-library/jest-dom/extend-expect'
beforeAll(() => {
beforeEach(() => {
document.body.innerHTML =

@@ -27,2 +27,6 @@ `<div dynamic-nested>

afterEach(() => {
document.body.innerHTML = ''
})
test('adds a new nested association markup incrementing +1 from the previous index', () => {

@@ -63,1 +67,26 @@ const element = document.querySelector('[dynamic-nested]')

test('supports callbacks beforeClone and afterAdd', () => {
const element = document.querySelector('[dynamic-nested]')
const beforeClone = (element) => {
element.setAttribute("data-before-clone", true)
}
const afterAdd = (element, newElement) => {
element.setAttribute("data-after-added", true)
newElement.setAttribute("data-after-added", true)
}
new DynamicNested(element, { beforeClone, afterAdd })
// Simulates a User clicks on add button.
document.querySelector('[dynamic-nested-add]').click()
const clonedElement = element.querySelector('[dynamic-nested-index="0"]')
const newElement = element.querySelector('[dynamic-nested-index="1"]')
expect(clonedElement).toHaveAttribute('data-before-clone', 'true')
expect(clonedElement).toHaveAttribute('data-after-added', 'true')
expect(newElement).toHaveAttribute('data-after-added', 'true')
})
import DynamicNested from '../index'
import '@testing-library/jest-dom/extend-expect'
beforeAll(() => {
beforeEach(() => {
document.body.innerHTML =

@@ -24,25 +24,25 @@ `<div dynamic-nested>

<button type="button" dynamic-nested-add>Add more</button>
`
`.trim()
})
describe("removing nested associations", () => {
test('removes the clicked nested and rebuild indexes', () => {
const element = document.querySelector('[dynamic-nested]')
const dynamicNested = new DynamicNested(element)
test('removes the clicked nested and rebuild indexes and support afterRemove callback', () => {
const element = document.querySelector('[dynamic-nested]')
// Simulates a User clicks on second nested association remove's button.
element
.querySelector('[dynamic-nested-index="1"]')
.querySelector('[dynamic-nested-remove]')
.click()
const afterRemove = (elements) => {
Array.from(elements).forEach(element => element.setAttribute('data-after-remove', true))
}
expect(element.querySelectorAll('[dynamic-nested-index]').length).toBe(2)
new DynamicNested(element, { afterRemove })
expect(element).toContainHTML(
'<div dynamic-nested-index="0">'
)
expect(element).toContainHTML(
'<div dynamic-nested-index="1">'
)
// Simulates a User clicks on second nested association remove's button.
element
.querySelector('[dynamic-nested-index="1"]')
.querySelector('[dynamic-nested-remove]')
.click()
expect(element.querySelectorAll('[dynamic-nested-index]').length).toBe(2)
Array.from(element.querySelectorAll('[dynamic-nested-index]')).forEach(element => {
expect(element).toHaveAttribute('data-after-remove', 'true')
})
})
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc