diff --git a/src/crank.ts b/src/crank.ts index 3cb89a73..a5bedc44 100644 --- a/src/crank.ts +++ b/src/crank.ts @@ -1935,12 +1935,27 @@ export class Context implements EventTarget { { setEventProperty(ev, "eventPhase", AT_TARGET); setEventProperty(ev, "currentTarget", ctx.owner); - const propCallback = ctx.ret.el.props["on" + ev.type] as unknown; + + // dispatchEvent calls the prop callback if it exists + let propCallback = ctx.ret.el.props["on" + ev.type] as unknown; if (typeof propCallback === "function") { propCallback(ev); if (immediateCancelBubble || ev.cancelBubble) { return true; } + } else { + // Checks for camel-cased event props + for (const propName in ctx.ret.el.props) { + if (propName.toLowerCase() === "on" + ev.type.toLowerCase()) { + propCallback = ctx.ret.el.props[propName] as unknown; + if (typeof propCallback === "function") { + propCallback(ev); + if (immediateCancelBubble || ev.cancelBubble) { + return true; + } + } + } + } } const listeners = listenersMap.get(ctx); diff --git a/test/events.tsx b/test/events.tsx index d7f75274..bc4a2fa9 100644 --- a/test/events.tsx +++ b/test/events.tsx @@ -337,6 +337,19 @@ test("event props", () => { Assert.is(mock.callCount, 1); }); +test("event props camelCased", () => { + let ctx!: Context; + function Component(this: Context, _props: {onFoo: (ev: Event) => any}) { + ctx = this; + return Hello; + } + + const mock = Sinon.fake(); + renderer.render(, document.body); + ctx.dispatchEvent(new Event("foo")); + Assert.is(mock.callCount, 1); +}); + test("error thrown in listener", () => { let ctx!: Context; function Component(this: Context) {