Skip to content

Commit

Permalink
Use getAttribute to find duplicate ids, not the id property
Browse files Browse the repository at this point in the history
Since form controls can be accessed in javascript directly by name through the form
object, (e.g. `my_form.my_input`), `c.id` may end up referring to an _element_
whose name is `id`, instead of referring to the global id _attribute_.
Explicitly retrieving the id with `getAttribute` avoids this.
  • Loading branch information
ethancrawford committed Dec 9, 2023
1 parent 098aafc commit f0928ab
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 3 deletions.
6 changes: 3 additions & 3 deletions src/elements/stream_element.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,10 @@ export class StreamElement extends HTMLElement {
* Gets the list of duplicate children (i.e. those with the same ID)
*/
get duplicateChildren() {
const existingChildren = this.targetElements.flatMap((e) => [...e.children]).filter((c) => !!c.id)
const newChildrenIds = [...(this.templateContent?.children || [])].filter((c) => !!c.id).map((c) => c.id)
const existingChildren = this.targetElements.flatMap((e) => [...e.children]).filter((c) => !!c.getAttribute("id"))
const newChildrenIds = [...(this.templateContent?.children || [])].filter((c) => !!c.getAttribute("id")).map((c) => c.getAttribute("id"))

return existingChildren.filter((c) => newChildrenIds.includes(c.id))
return existingChildren.filter((c) => newChildrenIds.includes(c.getAttribute("id")))
}

/**
Expand Down
50 changes: 50 additions & 0 deletions src/tests/unit/stream_element_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,33 @@ test("action=append", async () => {
assert.isNull(element2.parentElement)
})

test("action=append with a form template containing an input named id", async () => {
const element = createStreamElement(
"append",
"hello",
createTemplateElement(' <form id="child_1"><input type="hidden" name="id" value="First"></form> tail1 ')
)
const element2 = createStreamElement(
"append",
"hello",
createTemplateElement(
'<form id="child_1"><input type="hidden" name="id" value="New First"></form> <form id="child_2"><input type="hidden" name="id" value="Second"></form> tail2 '
)
)
assert.equal(subject.find("#hello")?.textContent, "Hello Turbo")

subject.append(element)
await nextAnimationFrame()

assert.equal(subject.find("#hello")?.innerHTML, 'Hello Turbo <form id="child_1"><input type="hidden" name="id" value="First"></form> tail1 ')
assert.isNull(element.parentElement)

subject.append(element2)
await nextAnimationFrame()

assert.equal(subject.find("#hello")?.innerHTML, 'Hello Turbo tail1 <form id="child_1"><input type="hidden" name="id" value="New First"></form> <form id="child_2"><input type="hidden" name="id" value="Second"></form> tail2 ')
})

test("action=append with children ID already present in target", async () => {
const element = createStreamElement("append", "hello", createTemplateElement(' <div id="child_1">First</div> tail1 '))
const element2 = createStreamElement(
Expand Down Expand Up @@ -87,6 +114,29 @@ test("action=prepend", async () => {
assert.isNull(element.parentElement)
})

test("action=prepend with a form template containing an input named id", async () => {
const element = createStreamElement("prepend", "hello", createTemplateElement('<form id="child_1"><input type="hidden" name="id" value="First"></form> tail1 '))
const element2 = createStreamElement(
"prepend",
"hello",
createTemplateElement(
'<form id="child_1"><input type="hidden" name="id" value="New First"></form> <form id="child_2"><input type="hidden" name="id" value="Second"></form> tail2 '
)
)
assert.equal(subject.find("#hello")?.textContent, "Hello Turbo")

subject.append(element)
await nextAnimationFrame()

assert.equal(subject.find("#hello")?.innerHTML, '<form id="child_1"><input type="hidden" name="id" value="First"></form> tail1 Hello Turbo')
assert.isNull(element.parentElement)

subject.append(element2)
await nextAnimationFrame()

assert.equal(subject.find("#hello")?.innerHTML, '<form id="child_1"><input type="hidden" name="id" value="New First"></form> <form id="child_2"><input type="hidden" name="id" value="Second"></form> tail2 tail1 Hello Turbo')
})

test("action=prepend with children ID already present in target", async () => {
const element = createStreamElement("prepend", "hello", createTemplateElement('<div id="child_1">First</div> tail1 '))
const element2 = createStreamElement(
Expand Down

0 comments on commit f0928ab

Please sign in to comment.