Skip to content

Commit 774fc5f

Browse files
Merge pull request #674 from universal-ember/copilot/fix-switch-onchange-arguments
Fix Switch `@onChange` argument order — pass `(checked: boolean, event: Event)`
2 parents af6681b + 179d7aa commit 774fc5f

2 files changed

Lines changed: 49 additions & 15 deletions

File tree

ember-primitives/src/components/switch.gts

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { fn, hash } from "@ember/helper";
1+
import Component from "@glimmer/component";
2+
import { hash } from "@ember/helper";
23
import { on } from "@ember/modifier";
34

45
import { cell } from "ember-resources";
56

67
import { uniqueId } from "../utils.ts";
78
import { Label } from "./-private/typed-elements.gts";
8-
import { toggleWithFallback } from "./-private/utils.ts";
99

1010
import type { TOC } from "@ember/component/template-only";
1111
import type { WithBoundArgs } from "@glint/template";
@@ -79,21 +79,37 @@ export interface Signature {
7979

8080
interface ControlSignature {
8181
Element: HTMLInputElement;
82-
Args: { id: string; checked?: ReturnType<typeof cell<boolean>>; onChange: () => void };
82+
Args: {
83+
id: string;
84+
checked?: ReturnType<typeof cell<boolean>>;
85+
onChange?: (checked: boolean, event: Event) => void;
86+
};
8387
}
8488

85-
const Checkbox: TOC<ControlSignature> = <template>
86-
<input
87-
id={{@id}}
88-
type="checkbox"
89-
role="switch"
90-
checked={{@checked.current}}
91-
aria-checked={{@checked.current}}
92-
data-state={{if @checked.current "on" "off"}}
93-
{{on "click" (fn toggleWithFallback @checked.toggle @onChange)}}
94-
...attributes
95-
/>
96-
</template>;
89+
class Checkbox extends Component<ControlSignature> {
90+
handleClick = (event: Event) => {
91+
const newChecked = (event.target as HTMLInputElement).checked;
92+
93+
if (this.args.onChange) {
94+
this.args.onChange(newChecked, event);
95+
} else {
96+
this.args.checked?.toggle();
97+
}
98+
};
99+
100+
<template>
101+
<input
102+
id={{@id}}
103+
type="checkbox"
104+
role="switch"
105+
checked={{@checked.current}}
106+
aria-checked={{@checked.current}}
107+
data-state={{if @checked.current "on" "off"}}
108+
{{on "click" this.handleClick}}
109+
...attributes
110+
/>
111+
</template>
112+
}
97113

98114
function defaultFalse(value: unknown) {
99115
return value ?? false;

test-app/tests/switch/rendering-test.gts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,22 @@ module('Switch', function (hooks) {
4343
await click('[role=switch]');
4444
assert.verifySteps(['false']);
4545
});
46+
47+
test('@onChange is called with (checked: boolean, event: Event)', async function (assert) {
48+
const calls: Array<[boolean, Event]> = [];
49+
const handleChange = (checked: boolean, event: Event) => calls.push([checked, event]);
50+
51+
await render(
52+
<template>
53+
<Switch @onChange={{handleChange}} as |s|>
54+
<s.Control />
55+
</Switch>
56+
</template>
57+
);
58+
59+
await click('[role=switch]');
60+
assert.strictEqual(calls.length, 1, 'onChange called once');
61+
assert.true(calls[0]?.[0], 'first arg is new checked state (true)');
62+
assert.ok(calls[0]?.[1] instanceof Event, 'second arg is an Event');
63+
});
4664
});

0 commit comments

Comments
 (0)