Skip to content

Commit 06a2375

Browse files
johnjenkinsJohn Jenkins
andauthored
fix(runtime): better boolean attribute handling (#6413)
* fix(runtime): better boolean attribute handling * chore: revert stencil weirdness * chore: more bool attr testing --------- Co-authored-by: John Jenkins <john.jenkins@nanoporetech.com>
1 parent 40516ea commit 06a2375

File tree

2 files changed

+70
-2
lines changed

2 files changed

+70
-2
lines changed

src/runtime/proxy-component.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -378,10 +378,16 @@ export const proxyComponent = (
378378
return;
379379
}
380380

381-
const propDesc = Object.getOwnPropertyDescriptor(prototype, propName);
381+
// special handling of boolean attributes. Null (removal) means false.
382+
// everything else means true (including an empty string
383+
const propFlags = members.find(([m]) => m === propName);
384+
if (propFlags && propFlags[1][0] & MEMBER_FLAGS.Boolean) {
385+
(newValue as any) = newValue === null || newValue === 'false' ? false : true;
386+
}
387+
382388
// test whether this property either has no 'getter' or if it does, does it also have a 'setter'
383389
// before attempting to write back to component props
384-
newValue = newValue === null && typeof this[propName] === 'boolean' ? (false as any) : newValue;
390+
const propDesc = Object.getOwnPropertyDescriptor(prototype, propName);
385391
if (newValue != this[propName] && (!propDesc.get || !!propDesc.set)) {
386392
this[propName] = newValue;
387393
}

src/runtime/test/attr.spec.tsx

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,14 @@ describe('attribute', () => {
6767

6868
expect(root.textContent).toBe('false');
6969
expect(root.bool).toBe(false);
70+
71+
// reset
72+
root.setAttribute('bool', '');
73+
expect(root.bool).toBe(true);
74+
75+
// check setAttribute
76+
root.setAttribute('bool', 'false');
77+
expect(root.bool).toBe(false);
7078
});
7179

7280
it('set boolean, undefined when missing attribute', async () => {
@@ -111,6 +119,14 @@ describe('attribute', () => {
111119

112120
expect(root.textContent).toBe('true');
113121
expect(root.bool).toBe(true);
122+
123+
// reset
124+
root.removeAttribute('bool');
125+
expect(root.bool).toBe(false);
126+
127+
// check setAttribute
128+
root.setAttribute('bool', 'true');
129+
expect(root.bool).toBe(true);
114130
});
115131

116132
it('set boolean true from no attribute value', async () => {
@@ -133,6 +149,14 @@ describe('attribute', () => {
133149

134150
expect(root.textContent).toBe('true');
135151
expect(root.bool).toBe(true);
152+
153+
// reset
154+
root.removeAttribute('bool');
155+
expect(root.bool).toBe(false);
156+
157+
// check setAttribute
158+
(root as HTMLElement).setAttribute('bool', '');
159+
expect(root.bool).toBe(true);
136160
});
137161

138162
it('set boolean true from empty string', async () => {
@@ -155,6 +179,44 @@ describe('attribute', () => {
155179

156180
expect(root.textContent).toBe('true');
157181
expect(root.bool).toBe(true);
182+
183+
// reset
184+
root.removeAttribute('bool');
185+
expect(root.bool).toBe(false);
186+
187+
// check setAttribute
188+
root.setAttribute('bool', '');
189+
expect(root.bool).toBe(true);
190+
});
191+
192+
it('set boolean true from any other string apart from "false"', async () => {
193+
@Component({ tag: 'cmp-a' })
194+
class CmpA {
195+
@Prop() bool: boolean;
196+
render() {
197+
return `${this.bool}`;
198+
}
199+
}
200+
201+
const { root } = await newSpecPage({
202+
components: [CmpA],
203+
html: `<cmp-a bool="nice"></cmp-a>`,
204+
});
205+
206+
expect(root).toEqualHtml(`
207+
<cmp-a bool="nice">true</cmp-a>
208+
`);
209+
210+
expect(root.textContent).toBe('true');
211+
expect(root.bool).toBe(true);
212+
213+
// reset
214+
root.removeAttribute('bool');
215+
expect(root.bool).toBe(false);
216+
217+
// check setAttribute
218+
root.setAttribute('bool', 'anything');
219+
expect(root.bool).toBe(true);
158220
});
159221

160222
it('set zero', async () => {

0 commit comments

Comments
 (0)