diff --git a/src/blockdom/attributes.ts b/src/blockdom/attributes.ts index b4e50760..dac1ece6 100644 --- a/src/blockdom/attributes.ts +++ b/src/blockdom/attributes.ts @@ -1,6 +1,6 @@ import type { Setter } from "./block_compiler"; -const { setAttribute, removeAttribute } = Element.prototype; +const { setAttribute: elemSetAttribute, removeAttribute } = Element.prototype; const tokenList = DOMTokenList.prototype; const tokenListAdd = tokenList.add; const tokenListRemove = tokenList.remove; @@ -14,11 +14,23 @@ const wordRegexp = /\s+/; * file. */ +function setAttribute(this: HTMLElement, key: string, value: any) { + switch (value) { + case false: + case undefined: + removeAttribute.call(this, key); + break; + case true: + elemSetAttribute.call(this, key, ""); + break; + default: + elemSetAttribute.call(this, key, value); + } +} + export function createAttrUpdater(attr: string): Setter { return function (this: HTMLElement, value: any) { - if (value !== false && value !== undefined) { - setAttribute.call(this, attr, value === true ? "" : value); - } + setAttribute.call(this, attr, value); }; } diff --git a/tests/blockdom/block_attributes.test.ts b/tests/blockdom/block_attributes.test.ts index fa015e1e..73e8417d 100644 --- a/tests/blockdom/block_attributes.test.ts +++ b/tests/blockdom/block_attributes.test.ts @@ -26,6 +26,26 @@ test("simple attribute", async () => { expect(fixture.innerHTML).toBe(`
`); }); +test("updating attribute with falsy value", async () => { + const block = createBlock('
'); + const tree = block([false]); + + mount(tree, fixture); + expect(fixture.innerHTML).toBe(`
`); + + patch(tree, block(["owl"])); + expect(fixture.innerHTML).toBe(`
`); + + patch(tree, block([false])); + expect(fixture.innerHTML).toBe(`
`); + + patch(tree, block(["owl"])); + expect(fixture.innerHTML).toBe(`
`); + + patch(tree, block([undefined])); + expect(fixture.innerHTML).toBe(`
`); +}); + test("dynamic attribute (pair)", async () => { const block = createBlock('
'); const tree = block([["hello", "world"]]); @@ -37,6 +57,20 @@ test("dynamic attribute (pair)", async () => { expect(fixture.innerHTML).toBe(`
`); }); +test("dynamic attribute (pair, with false value)", async () => { + const block = createBlock('
'); + const tree = block([["hello", false]]); + + mount(tree, fixture); + expect(fixture.innerHTML).toBe(`
`); + + patch(tree, block([["hello", "world"]])); + expect(fixture.innerHTML).toBe(`
`); + + patch(tree, block([["hello", false]])); + expect(fixture.innerHTML).toBe(`
`); +}); + test("dynamic attribute (object)", async () => { const block = createBlock('
'); const tree = block([{ hello: "world" }]); @@ -48,6 +82,23 @@ test("dynamic attribute (object)", async () => { expect(fixture.innerHTML).toBe(`
`); }); +test("dynamic attribute (object), with falsy values", async () => { + const block = createBlock('
'); + const tree = block([{ hello: "world", blip: false }]); + + mount(tree, fixture); + expect(fixture.innerHTML).toBe(`
`); + + patch(tree, block([{ ola: "mundo", blip: undefined }])); + expect(fixture.innerHTML).toBe(`
`); + + patch(tree, block([{ ola: false, blip: 1 }])); + expect(fixture.innerHTML).toBe(`
`); + + patch(tree, block([{ ola: undefined, blip: undefined }])); + expect(fixture.innerHTML).toBe(`
`); +}); + test("class attribute", async () => { const block = createBlock('
'); const tree = block(["fire"]);