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 Feb 23, 2023
1 parent e013072 commit be3ff38
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 3 deletions.
6 changes: 3 additions & 3 deletions src/elements/stream_element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,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
42 changes: 42 additions & 0 deletions src/tests/unit/stream_element_tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,27 @@ test("test action=append with children ID already present in target", async () =
assert.equal(subject.find("#hello")?.textContent, "Hello Turbo tail1 New First Second tail2 ")
})

test("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("test action=prepend", async () => {
const element = createStreamElement("prepend", "hello", createTemplateElement("<span>Streams </span>"))
const element2 = createStreamElement("prepend", "hello", createTemplateElement("<span>and more </span>"))
Expand Down Expand Up @@ -106,6 +127,27 @@ test("test action=prepend with children ID already present in target", async ()
assert.equal(subject.find("#hello")?.textContent, "New First Second tail2 tail1 Hello Turbo")
})

test("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("test action=remove", async () => {
const element = createStreamElement("remove", "hello")
assert.ok(subject.find("#hello"))
Expand Down

0 comments on commit be3ff38

Please sign in to comment.