From e7407890ffccc62372af6791b4689f27841d9cde Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20Wei=C3=9F?=
<7667003+bastiW@users.noreply.github.com>
Date: Thu, 26 Sep 2024 13:48:40 +0200
Subject: [PATCH 1/5] Remove on prefix on Angular Events
Remove on prefix on Angular Events
---
e2e/e2e-app/src/component-paths.ts | 1 +
.../components/events/event-child.lite.tsx | 25 +++++
.../components/events/event-parent.lite.tsx | 28 ++++++
e2e/e2e-app/src/homepage.lite.tsx | 5 +
e2e/e2e-app/tests/main.spec.ts | 25 ++++-
examples/basic/src/blocks/modal.lite.tsx | 27 ++++++
.../basic/src/index-helpers/blocks-exports.ts | 2 +-
.../__snapshots__/angular.import.test.ts.snap | 48 +++++-----
.../__snapshots__/angular.mapper.test.ts.snap | 48 +++++-----
.../__snapshots__/angular.state.test.ts.snap | 48 +++++-----
.../__snapshots__/angular.styles.test.ts.snap | 48 +++++-----
.../__snapshots__/angular.test.ts.snap | 96 +++++++++----------
packages/core/src/generators/angular/index.ts | 15 ++-
.../src/helpers/strip-state-and-props-refs.ts | 3 +-
packages/core/src/parsers/angular.ts | 2 +-
15 files changed, 269 insertions(+), 152 deletions(-)
create mode 100644 e2e/e2e-app/src/components/events/event-child.lite.tsx
create mode 100644 e2e/e2e-app/src/components/events/event-parent.lite.tsx
create mode 100644 examples/basic/src/blocks/modal.lite.tsx
diff --git a/e2e/e2e-app/src/component-paths.ts b/e2e/e2e-app/src/component-paths.ts
index 11a06ff467..6cc2e2862b 100644
--- a/e2e/e2e-app/src/component-paths.ts
+++ b/e2e/e2e-app/src/component-paths.ts
@@ -6,4 +6,5 @@ export const COMPONENT_PATHS = [
'/special-tags/',
'/signals/',
'/disabled-input/',
+ '/event-listener/',
];
diff --git a/e2e/e2e-app/src/components/events/event-child.lite.tsx b/e2e/e2e-app/src/components/events/event-child.lite.tsx
new file mode 100644
index 0000000000..7c046375a0
--- /dev/null
+++ b/e2e/e2e-app/src/components/events/event-child.lite.tsx
@@ -0,0 +1,25 @@
+import { useStore } from '@builder.io/mitosis';
+
+export interface EventChildProps {
+ onConfirm: (name: string) => void;
+ onCancel: () => void;
+}
+
+export default function EventChild(props: EventChildProps) {
+ const state = useStore({
+ _onCancel() {
+ props.onCancel();
+ },
+
+ _onConfirm() {
+ props.onConfirm('Joe');
+ },
+ });
+
+ return (
+ <>
+
+
+ >
+ );
+}
diff --git a/e2e/e2e-app/src/components/events/event-parent.lite.tsx b/e2e/e2e-app/src/components/events/event-parent.lite.tsx
new file mode 100644
index 0000000000..71e5527314
--- /dev/null
+++ b/e2e/e2e-app/src/components/events/event-parent.lite.tsx
@@ -0,0 +1,28 @@
+import { useState, useStore } from '@builder.io/mitosis';
+import EventChild from './event-child.lite';
+
+export default function EventParent() {
+ const [eventLog, setEventLog] = useState('');
+
+ const state = useStore({
+ _onCancel() {
+ const newEventLog = eventLog + 'Cancel event called
';
+ setEventLog(newEventLog);
+ },
+
+ _onConfirm(name: string) {
+ const newEventLog = eventLog + `Confirm event called with parameter: ${name}
`;
+ setEventLog(newEventLog);
+ },
+ });
+
+ return (
+ <>
+ state._onConfirm(name)}
+ onCancel={() => state._onCancel()}
+ >
+
+ >
+ );
+}
diff --git a/e2e/e2e-app/src/homepage.lite.tsx b/e2e/e2e-app/src/homepage.lite.tsx
index 854dc7669b..b4e3cd9a71 100644
--- a/e2e/e2e-app/src/homepage.lite.tsx
+++ b/e2e/e2e-app/src/homepage.lite.tsx
@@ -2,6 +2,7 @@ import { For, onMount, Show, useStore } from '@builder.io/mitosis';
import { COMPONENT_PATHS } from './component-paths';
import ComponentWithTypes from './components/component-with-types.lite';
import DisabledInput from './components/disabled-input/disabled-input.lite';
+import EventParent from './components/events/event-parent.lite';
import NestedParent from './components/nested/nested-parent.lite';
import OneComponent from './components/one-component.lite';
import ShowForComponent from './components/show-for-component.lite';
@@ -61,6 +62,10 @@ export default function Homepage(props: { pathname?: string }) {
+
+
+
+
);
}
diff --git a/e2e/e2e-app/tests/main.spec.ts b/e2e/e2e-app/tests/main.spec.ts
index 4413323240..7a5df79e79 100644
--- a/e2e/e2e-app/tests/main.spec.ts
+++ b/e2e/e2e-app/tests/main.spec.ts
@@ -46,7 +46,6 @@ test.describe('e2e', () => {
await expect(page.locator(`${textLocator}2`)).toBeVisible();
await expect(page.locator(`${textLocator}3`)).toBeVisible();
});
-
test.describe('special HTML tags', () => {
test('template tag', async ({ page, packageName }) => {
await page.goto('/special-tags/');
@@ -101,4 +100,28 @@ test.describe('e2e', () => {
await expect(nativeEnabled).toBeEditable();
});
});
+
+ test.describe('Event Listener', () => {
+ test('Single Event without parameter', async ({ page, packageName }) => {
+ await page.goto('/event-listener/');
+
+ const cancelButton = page.getByRole('button', { name: 'Cancel' });
+
+ await cancelButton.click();
+
+ await expect(page.getByTestId('event-log')).toHaveText('Cancel event called');
+ });
+
+ test('Single Event with parameter', async ({ page, packageName }) => {
+ await page.goto('/event-listener/');
+
+ const confirmButton = page.getByRole('button', { name: 'Confirm' });
+
+ await confirmButton.click();
+
+ await expect(page.getByTestId('event-log')).toHaveText(
+ 'Confirm event called with parameter: Joe',
+ );
+ });
+ });
});
diff --git a/examples/basic/src/blocks/modal.lite.tsx b/examples/basic/src/blocks/modal.lite.tsx
new file mode 100644
index 0000000000..fc02812d34
--- /dev/null
+++ b/examples/basic/src/blocks/modal.lite.tsx
@@ -0,0 +1,27 @@
+import {useStore} from '@builder.io/mitosis';
+
+export interface ModalProps {
+ onConfirm: (name: string) => void;
+ onCancel: () => void;
+}
+
+export default function Modal(props: ModalProps) {
+
+ const state = useStore({
+ _onCancel() {
+ props.onCancel()
+ },
+
+ _onConfirm() {
+ props.onConfirm('Joe')
+ },
+ });
+
+
+ return (
+ <>
+
+
+ >
+ );
+}
diff --git a/examples/basic/src/index-helpers/blocks-exports.ts b/examples/basic/src/index-helpers/blocks-exports.ts
index 617105ec9b..82d4faf4f0 100644
--- a/examples/basic/src/index-helpers/blocks-exports.ts
+++ b/examples/basic/src/index-helpers/blocks-exports.ts
@@ -1,2 +1,2 @@
export { default as Button } from '../blocks/button.lite';
-export { default as Image } from '../blocks/image.lite';
+export { default as Image } from '../blocks/image.lite';
\ No newline at end of file
diff --git a/packages/core/src/__tests__/__snapshots__/angular.import.test.ts.snap b/packages/core/src/__tests__/__snapshots__/angular.import.test.ts.snap
index fb6da252b3..46006dd0e6 100644
--- a/packages/core/src/__tests__/__snapshots__/angular.import.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/angular.import.test.ts.snap
@@ -294,15 +294,15 @@ import { Output, EventEmitter, Component, Input } from \\"@angular/core\\";
export default class MyBasicOutputsComponent {
@Input() message;
- @Output() onMessage = new EventEmitter();
- @Output() onEvent = new EventEmitter();
+ @Output() message = new EventEmitter();
+ @Output() event = new EventEmitter();
name = \\"PatrickJS\\";
ngOnInit() {
if (typeof window !== \\"undefined\\") {
- this.onMessage.emit(this.name);
- this.onEvent.emit(this.message);
+ this.message.emit(this.name);
+ this.event.emit(this.message);
}
}
}
@@ -338,15 +338,15 @@ import { Output, EventEmitter, Component, Input } from \\"@angular/core\\";
export default class MyBasicOutputsComponent {
@Input() message;
- @Output() onMessage = new EventEmitter();
- @Output() onEvent = new EventEmitter();
+ @Output() message = new EventEmitter();
+ @Output() event = new EventEmitter();
name = \\"PatrickJS\\";
ngOnInit() {
if (typeof window !== \\"undefined\\") {
- this.onMessage.emit(this.name);
- this.onEvent.emit(this.message);
+ this.message.emit(this.name);
+ this.event.emit(this.message);
}
}
}
@@ -3694,7 +3694,7 @@ const defaultProps = {
-
@@ -3715,7 +3715,7 @@ export default class Button {
@Input() text = defaultProps[\\"text\\"];
@Input() buttonText;
- @Output() onClick = new EventEmitter();
+ @Output() click = new EventEmitter();
@ViewChild(\\"elRef0\\") elRef0;
@ViewChild(\\"elRef1\\") elRef1;
@@ -3821,7 +3821,7 @@ const defaultProps = {
-
+
{{text}}
@@ -3841,7 +3841,7 @@ export default class Button {
@Input() openLinkInNewTab = defaultProps[\\"openLinkInNewTab\\"];
@Input() text = defaultProps[\\"text\\"];
- @Output() onClick = new EventEmitter();
+ @Output() click = new EventEmitter();
@ViewChild(\\"elRef0\\") elRef0;
@ViewChild(\\"elRef1\\") elRef1;
@@ -7144,15 +7144,15 @@ import { Output, EventEmitter, Component, Input } from \\"@angular/core\\";
export default class MyBasicOutputsComponent {
@Input() message!: any;
- @Output() onMessage = new EventEmitter();
- @Output() onEvent = new EventEmitter();
+ @Output() message = new EventEmitter();
+ @Output() event = new EventEmitter();
name = \\"PatrickJS\\";
ngOnInit() {
if (typeof window !== \\"undefined\\") {
- this.onMessage.emit(this.name);
- this.onEvent.emit(this.message);
+ this.message.emit(this.name);
+ this.event.emit(this.message);
}
}
}
@@ -7188,15 +7188,15 @@ import { Output, EventEmitter, Component, Input } from \\"@angular/core\\";
export default class MyBasicOutputsComponent {
@Input() message!: any;
- @Output() onMessage = new EventEmitter();
- @Output() onEvent = new EventEmitter();
+ @Output() message = new EventEmitter();
+ @Output() event = new EventEmitter();
name = \\"PatrickJS\\";
ngOnInit() {
if (typeof window !== \\"undefined\\") {
- this.onMessage.emit(this.name);
- this.onEvent.emit(this.message);
+ this.message.emit(this.name);
+ this.event.emit(this.message);
}
}
}
@@ -10828,7 +10828,7 @@ const defaultProps = {
-
+
{{buttonText}}
@@ -10850,7 +10850,7 @@ export default class Button {
@Input() text!: ButtonProps[\\"text\\"] = defaultProps[\\"text\\"];
@Input() buttonText!: ButtonProps[\\"buttonText\\"];
- @Output() onClick = new EventEmitter();
+ @Output() click = new EventEmitter();
@ViewChild(\\"elRef0\\") elRef0!: ElementRef;
@ViewChild(\\"elRef1\\") elRef1!: ElementRef;
@@ -10964,7 +10964,7 @@ const defaultProps = {
-
+
{{text}}
@@ -10985,7 +10985,7 @@ export default class Button {
defaultProps[\\"openLinkInNewTab\\"];
@Input() text!: ButtonProps[\\"text\\"] = defaultProps[\\"text\\"];
- @Output() onClick = new EventEmitter();
+ @Output() click = new EventEmitter();
@ViewChild(\\"elRef0\\") elRef0!: ElementRef;
@ViewChild(\\"elRef1\\") elRef1!: ElementRef;
diff --git a/packages/core/src/__tests__/__snapshots__/angular.mapper.test.ts.snap b/packages/core/src/__tests__/__snapshots__/angular.mapper.test.ts.snap
index 4b8db0d072..f2e45ab9cb 100644
--- a/packages/core/src/__tests__/__snapshots__/angular.mapper.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/angular.mapper.test.ts.snap
@@ -299,15 +299,15 @@ import { Output, EventEmitter, Component, Input } from \\"@angular/core\\";
export default class MyBasicOutputsComponent {
@Input() message;
- @Output() onMessage = new EventEmitter();
- @Output() onEvent = new EventEmitter();
+ @Output() message = new EventEmitter();
+ @Output() event = new EventEmitter();
name = \\"PatrickJS\\";
ngOnInit() {
if (typeof window !== \\"undefined\\") {
- this.onMessage.emit(this.name);
- this.onEvent.emit(this.message);
+ this.message.emit(this.name);
+ this.event.emit(this.message);
}
}
}
@@ -344,15 +344,15 @@ import { Output, EventEmitter, Component, Input } from \\"@angular/core\\";
export default class MyBasicOutputsComponent {
@Input() message;
- @Output() onMessage = new EventEmitter();
- @Output() onEvent = new EventEmitter();
+ @Output() message = new EventEmitter();
+ @Output() event = new EventEmitter();
name = \\"PatrickJS\\";
ngOnInit() {
if (typeof window !== \\"undefined\\") {
- this.onMessage.emit(this.name);
- this.onEvent.emit(this.message);
+ this.message.emit(this.name);
+ this.event.emit(this.message);
}
}
}
@@ -3748,7 +3748,7 @@ const defaultProps = {
-
+
{{buttonText}}
@@ -3769,7 +3769,7 @@ export default class Button {
@Input() text = defaultProps[\\"text\\"];
@Input() buttonText;
- @Output() onClick = new EventEmitter();
+ @Output() click = new EventEmitter();
@ViewChild(\\"elRef0\\") elRef0;
@ViewChild(\\"elRef1\\") elRef1;
@@ -3876,7 +3876,7 @@ const defaultProps = {
-
+
{{text}}
@@ -3896,7 +3896,7 @@ export default class Button {
@Input() openLinkInNewTab = defaultProps[\\"openLinkInNewTab\\"];
@Input() text = defaultProps[\\"text\\"];
- @Output() onClick = new EventEmitter();
+ @Output() click = new EventEmitter();
@ViewChild(\\"elRef0\\") elRef0;
@ViewChild(\\"elRef1\\") elRef1;
@@ -7262,15 +7262,15 @@ import { Output, EventEmitter, Component, Input } from \\"@angular/core\\";
export default class MyBasicOutputsComponent {
@Input() message!: any;
- @Output() onMessage = new EventEmitter();
- @Output() onEvent = new EventEmitter();
+ @Output() message = new EventEmitter();
+ @Output() event = new EventEmitter();
name = \\"PatrickJS\\";
ngOnInit() {
if (typeof window !== \\"undefined\\") {
- this.onMessage.emit(this.name);
- this.onEvent.emit(this.message);
+ this.message.emit(this.name);
+ this.event.emit(this.message);
}
}
}
@@ -7307,15 +7307,15 @@ import { Output, EventEmitter, Component, Input } from \\"@angular/core\\";
export default class MyBasicOutputsComponent {
@Input() message!: any;
- @Output() onMessage = new EventEmitter();
- @Output() onEvent = new EventEmitter();
+ @Output() message = new EventEmitter();
+ @Output() event = new EventEmitter();
name = \\"PatrickJS\\";
ngOnInit() {
if (typeof window !== \\"undefined\\") {
- this.onMessage.emit(this.name);
- this.onEvent.emit(this.message);
+ this.message.emit(this.name);
+ this.event.emit(this.message);
}
}
}
@@ -10995,7 +10995,7 @@ const defaultProps = {
-
+
{{buttonText}}
@@ -11017,7 +11017,7 @@ export default class Button {
@Input() text!: ButtonProps[\\"text\\"] = defaultProps[\\"text\\"];
@Input() buttonText!: ButtonProps[\\"buttonText\\"];
- @Output() onClick = new EventEmitter();
+ @Output() click = new EventEmitter();
@ViewChild(\\"elRef0\\") elRef0!: ElementRef;
@ViewChild(\\"elRef1\\") elRef1!: ElementRef;
@@ -11132,7 +11132,7 @@ const defaultProps = {
-
+
{{text}}
@@ -11153,7 +11153,7 @@ export default class Button {
defaultProps[\\"openLinkInNewTab\\"];
@Input() text!: ButtonProps[\\"text\\"] = defaultProps[\\"text\\"];
- @Output() onClick = new EventEmitter();
+ @Output() click = new EventEmitter();
@ViewChild(\\"elRef0\\") elRef0!: ElementRef;
@ViewChild(\\"elRef1\\") elRef1!: ElementRef;
diff --git a/packages/core/src/__tests__/__snapshots__/angular.state.test.ts.snap b/packages/core/src/__tests__/__snapshots__/angular.state.test.ts.snap
index 164a92c9ef..d3afefc11e 100644
--- a/packages/core/src/__tests__/__snapshots__/angular.state.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/angular.state.test.ts.snap
@@ -306,15 +306,15 @@ import { Output, EventEmitter, Component, Input } from \\"@angular/core\\";
export default class MyBasicOutputsComponent {
@Input() message;
- @Output() onMessage = new EventEmitter();
- @Output() onEvent = new EventEmitter();
+ @Output() message = new EventEmitter();
+ @Output() event = new EventEmitter();
name = \\"PatrickJS\\";
ngOnInit() {
if (typeof window !== \\"undefined\\") {
- this.onMessage.emit(this.name);
- this.onEvent.emit(this.message);
+ this.message.emit(this.name);
+ this.event.emit(this.message);
}
}
}
@@ -350,15 +350,15 @@ import { Output, EventEmitter, Component, Input } from \\"@angular/core\\";
export default class MyBasicOutputsComponent {
@Input() message;
- @Output() onMessage = new EventEmitter();
- @Output() onEvent = new EventEmitter();
+ @Output() message = new EventEmitter();
+ @Output() event = new EventEmitter();
name = \\"PatrickJS\\";
ngOnInit() {
if (typeof window !== \\"undefined\\") {
- this.onMessage.emit(this.name);
- this.onEvent.emit(this.message);
+ this.message.emit(this.name);
+ this.event.emit(this.message);
}
}
}
@@ -3797,7 +3797,7 @@ const defaultProps = {
-
+
{{buttonText}}
@@ -3818,7 +3818,7 @@ export default class Button {
@Input() text = defaultProps[\\"text\\"];
@Input() buttonText;
- @Output() onClick = new EventEmitter();
+ @Output() click = new EventEmitter();
@ViewChild(\\"elRef0\\") elRef0;
@ViewChild(\\"elRef1\\") elRef1;
@@ -3924,7 +3924,7 @@ const defaultProps = {
-
+
{{text}}
@@ -3944,7 +3944,7 @@ export default class Button {
@Input() openLinkInNewTab = defaultProps[\\"openLinkInNewTab\\"];
@Input() text = defaultProps[\\"text\\"];
- @Output() onClick = new EventEmitter();
+ @Output() click = new EventEmitter();
@ViewChild(\\"elRef0\\") elRef0;
@ViewChild(\\"elRef1\\") elRef1;
@@ -7376,15 +7376,15 @@ import { Output, EventEmitter, Component, Input } from \\"@angular/core\\";
export default class MyBasicOutputsComponent {
@Input() message!: any;
- @Output() onMessage = new EventEmitter();
- @Output() onEvent = new EventEmitter();
+ @Output() message = new EventEmitter();
+ @Output() event = new EventEmitter();
name = \\"PatrickJS\\";
ngOnInit() {
if (typeof window !== \\"undefined\\") {
- this.onMessage.emit(this.name);
- this.onEvent.emit(this.message);
+ this.message.emit(this.name);
+ this.event.emit(this.message);
}
}
}
@@ -7420,15 +7420,15 @@ import { Output, EventEmitter, Component, Input } from \\"@angular/core\\";
export default class MyBasicOutputsComponent {
@Input() message!: any;
- @Output() onMessage = new EventEmitter();
- @Output() onEvent = new EventEmitter();
+ @Output() message = new EventEmitter();
+ @Output() event = new EventEmitter();
name = \\"PatrickJS\\";
ngOnInit() {
if (typeof window !== \\"undefined\\") {
- this.onMessage.emit(this.name);
- this.onEvent.emit(this.message);
+ this.message.emit(this.name);
+ this.event.emit(this.message);
}
}
}
@@ -11176,7 +11176,7 @@ const defaultProps = {
-
+
{{buttonText}}
@@ -11198,7 +11198,7 @@ export default class Button {
@Input() text!: ButtonProps[\\"text\\"] = defaultProps[\\"text\\"];
@Input() buttonText!: ButtonProps[\\"buttonText\\"];
- @Output() onClick = new EventEmitter();
+ @Output() click = new EventEmitter();
@ViewChild(\\"elRef0\\") elRef0!: ElementRef;
@ViewChild(\\"elRef1\\") elRef1!: ElementRef;
@@ -11312,7 +11312,7 @@ const defaultProps = {
-
+
{{text}}
@@ -11333,7 +11333,7 @@ export default class Button {
defaultProps[\\"openLinkInNewTab\\"];
@Input() text!: ButtonProps[\\"text\\"] = defaultProps[\\"text\\"];
- @Output() onClick = new EventEmitter();
+ @Output() click = new EventEmitter();
@ViewChild(\\"elRef0\\") elRef0!: ElementRef;
@ViewChild(\\"elRef1\\") elRef1!: ElementRef;
diff --git a/packages/core/src/__tests__/__snapshots__/angular.styles.test.ts.snap b/packages/core/src/__tests__/__snapshots__/angular.styles.test.ts.snap
index 41e4307ae4..c5e908172a 100644
--- a/packages/core/src/__tests__/__snapshots__/angular.styles.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/angular.styles.test.ts.snap
@@ -260,15 +260,15 @@ import { Output, EventEmitter, Component, Input } from \\"@angular/core\\";
export default class MyBasicOutputsComponent {
@Input() message;
- @Output() onMessage = new EventEmitter();
- @Output() onEvent = new EventEmitter();
+ @Output() message = new EventEmitter();
+ @Output() event = new EventEmitter();
name = \\"PatrickJS\\";
ngOnInit() {
if (typeof window !== \\"undefined\\") {
- this.onMessage.emit(this.name);
- this.onEvent.emit(this.message);
+ this.message.emit(this.name);
+ this.event.emit(this.message);
}
}
}
@@ -297,15 +297,15 @@ import { Output, EventEmitter, Component, Input } from \\"@angular/core\\";
export default class MyBasicOutputsComponent {
@Input() message;
- @Output() onMessage = new EventEmitter();
- @Output() onEvent = new EventEmitter();
+ @Output() message = new EventEmitter();
+ @Output() event = new EventEmitter();
name = \\"PatrickJS\\";
ngOnInit() {
if (typeof window !== \\"undefined\\") {
- this.onMessage.emit(this.name);
- this.onEvent.emit(this.message);
+ this.message.emit(this.name);
+ this.event.emit(this.message);
}
}
}
@@ -3366,7 +3366,7 @@ const defaultProps = {
-
+
{{buttonText}}
@@ -3380,7 +3380,7 @@ export default class Button {
@Input() text = defaultProps[\\"text\\"];
@Input() buttonText;
- @Output() onClick = new EventEmitter();
+ @Output() click = new EventEmitter();
@ViewChild(\\"elRef0\\") elRef0;
@ViewChild(\\"elRef1\\") elRef1;
@@ -3486,7 +3486,7 @@ const defaultProps = {
-
+
{{text}}
@@ -3499,7 +3499,7 @@ export default class Button {
@Input() openLinkInNewTab = defaultProps[\\"openLinkInNewTab\\"];
@Input() text = defaultProps[\\"text\\"];
- @Output() onClick = new EventEmitter();
+ @Output() click = new EventEmitter();
@ViewChild(\\"elRef0\\") elRef0;
@ViewChild(\\"elRef1\\") elRef1;
@@ -6393,15 +6393,15 @@ import { Output, EventEmitter, Component, Input } from \\"@angular/core\\";
export default class MyBasicOutputsComponent {
@Input() message!: any;
- @Output() onMessage = new EventEmitter();
- @Output() onEvent = new EventEmitter();
+ @Output() message = new EventEmitter();
+ @Output() event = new EventEmitter();
name = \\"PatrickJS\\";
ngOnInit() {
if (typeof window !== \\"undefined\\") {
- this.onMessage.emit(this.name);
- this.onEvent.emit(this.message);
+ this.message.emit(this.name);
+ this.event.emit(this.message);
}
}
}
@@ -6430,15 +6430,15 @@ import { Output, EventEmitter, Component, Input } from \\"@angular/core\\";
export default class MyBasicOutputsComponent {
@Input() message!: any;
- @Output() onMessage = new EventEmitter();
- @Output() onEvent = new EventEmitter();
+ @Output() message = new EventEmitter();
+ @Output() event = new EventEmitter();
name = \\"PatrickJS\\";
ngOnInit() {
if (typeof window !== \\"undefined\\") {
- this.onMessage.emit(this.name);
- this.onEvent.emit(this.message);
+ this.message.emit(this.name);
+ this.event.emit(this.message);
}
}
}
@@ -9783,7 +9783,7 @@ const defaultProps = {
-
+
{{buttonText}}
@@ -9798,7 +9798,7 @@ export default class Button {
@Input() text!: ButtonProps[\\"text\\"] = defaultProps[\\"text\\"];
@Input() buttonText!: ButtonProps[\\"buttonText\\"];
- @Output() onClick = new EventEmitter();
+ @Output() click = new EventEmitter();
@ViewChild(\\"elRef0\\") elRef0!: ElementRef;
@ViewChild(\\"elRef1\\") elRef1!: ElementRef;
@@ -9912,7 +9912,7 @@ const defaultProps = {
-
+
{{text}}
@@ -9926,7 +9926,7 @@ export default class Button {
defaultProps[\\"openLinkInNewTab\\"];
@Input() text!: ButtonProps[\\"text\\"] = defaultProps[\\"text\\"];
- @Output() onClick = new EventEmitter();
+ @Output() click = new EventEmitter();
@ViewChild(\\"elRef0\\") elRef0!: ElementRef;
@ViewChild(\\"elRef1\\") elRef1!: ElementRef;
diff --git a/packages/core/src/__tests__/__snapshots__/angular.test.ts.snap b/packages/core/src/__tests__/__snapshots__/angular.test.ts.snap
index 1f9225a34e..988c57ced1 100644
--- a/packages/core/src/__tests__/__snapshots__/angular.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/angular.test.ts.snap
@@ -531,15 +531,15 @@ import { Output, EventEmitter, Component, Input } from \\"@angular/core\\";
export default class MyBasicOutputsComponent {
@Input() message;
- @Output() onMessage = new EventEmitter();
- @Output() onEvent = new EventEmitter();
+ @Output() message = new EventEmitter();
+ @Output() event = new EventEmitter();
name = \\"PatrickJS\\";
ngOnInit() {
if (typeof window !== \\"undefined\\") {
- this.onMessage.emit(this.name);
- this.onEvent.emit(this.message);
+ this.message.emit(this.name);
+ this.event.emit(this.message);
}
}
}
@@ -575,15 +575,15 @@ import { CommonModule } from \\"@angular/common\\";
export default class MyBasicOutputsComponent {
@Input() message;
- @Output() onMessage = new EventEmitter();
- @Output() onEvent = new EventEmitter();
+ @Output() message = new EventEmitter();
+ @Output() event = new EventEmitter();
name = \\"PatrickJS\\";
ngOnInit() {
if (typeof window !== \\"undefined\\") {
- this.onMessage.emit(this.name);
- this.onEvent.emit(this.message);
+ this.message.emit(this.name);
+ this.event.emit(this.message);
}
}
}
@@ -612,15 +612,15 @@ import { Output, EventEmitter, Component, Input } from \\"@angular/core\\";
export default class MyBasicOutputsComponent {
@Input() message;
- @Output() onMessage = new EventEmitter();
- @Output() onEvent = new EventEmitter();
+ @Output() message = new EventEmitter();
+ @Output() event = new EventEmitter();
name = \\"PatrickJS\\";
ngOnInit() {
if (typeof window !== \\"undefined\\") {
- this.onMessage.emit(this.name);
- this.onEvent.emit(this.message);
+ this.message.emit(this.name);
+ this.event.emit(this.message);
}
}
}
@@ -656,15 +656,15 @@ import { CommonModule } from \\"@angular/common\\";
export default class MyBasicOutputsComponent {
@Input() message;
- @Output() onMessage = new EventEmitter();
- @Output() onEvent = new EventEmitter();
+ @Output() message = new EventEmitter();
+ @Output() event = new EventEmitter();
name = \\"PatrickJS\\";
ngOnInit() {
if (typeof window !== \\"undefined\\") {
- this.onMessage.emit(this.name);
- this.onEvent.emit(this.message);
+ this.message.emit(this.name);
+ this.event.emit(this.message);
}
}
}
@@ -6967,7 +6967,7 @@ const defaultProps = {
-
+
{{buttonText}}
@@ -6988,7 +6988,7 @@ export default class Button {
@Input() text = defaultProps[\\"text\\"];
@Input() buttonText;
- @Output() onClick = new EventEmitter();
+ @Output() click = new EventEmitter();
@ViewChild(\\"elRef0\\") elRef0;
@ViewChild(\\"elRef1\\") elRef1;
@@ -7094,7 +7094,7 @@ const defaultProps = {
-
+
{{buttonText}}
@@ -7117,7 +7117,7 @@ export default class Button {
@Input() text = defaultProps[\\"text\\"];
@Input() buttonText;
- @Output() onClick = new EventEmitter();
+ @Output() click = new EventEmitter();
@ViewChild(\\"elRef0\\") elRef0;
@ViewChild(\\"elRef1\\") elRef1;
@@ -7216,7 +7216,7 @@ const defaultProps = {
-
+
{{text}}
@@ -7236,7 +7236,7 @@ export default class Button {
@Input() openLinkInNewTab = defaultProps[\\"openLinkInNewTab\\"];
@Input() text = defaultProps[\\"text\\"];
- @Output() onClick = new EventEmitter();
+ @Output() click = new EventEmitter();
@ViewChild(\\"elRef0\\") elRef0;
@ViewChild(\\"elRef1\\") elRef1;
@@ -7340,7 +7340,7 @@ const defaultProps = {
-
+
{{text}}
@@ -7362,7 +7362,7 @@ export default class Button {
@Input() openLinkInNewTab = defaultProps[\\"openLinkInNewTab\\"];
@Input() text = defaultProps[\\"text\\"];
- @Output() onClick = new EventEmitter();
+ @Output() click = new EventEmitter();
@ViewChild(\\"elRef0\\") elRef0;
@ViewChild(\\"elRef1\\") elRef1;
@@ -13410,15 +13410,15 @@ import { Output, EventEmitter, Component, Input } from \\"@angular/core\\";
export default class MyBasicOutputsComponent {
@Input() message!: any;
- @Output() onMessage = new EventEmitter();
- @Output() onEvent = new EventEmitter();
+ @Output() message = new EventEmitter();
+ @Output() event = new EventEmitter();
name = \\"PatrickJS\\";
ngOnInit() {
if (typeof window !== \\"undefined\\") {
- this.onMessage.emit(this.name);
- this.onEvent.emit(this.message);
+ this.message.emit(this.name);
+ this.event.emit(this.message);
}
}
}
@@ -13454,15 +13454,15 @@ import { CommonModule } from \\"@angular/common\\";
export default class MyBasicOutputsComponent {
@Input() message!: any;
- @Output() onMessage = new EventEmitter();
- @Output() onEvent = new EventEmitter();
+ @Output() message = new EventEmitter();
+ @Output() event = new EventEmitter();
name = \\"PatrickJS\\";
ngOnInit() {
if (typeof window !== \\"undefined\\") {
- this.onMessage.emit(this.name);
- this.onEvent.emit(this.message);
+ this.message.emit(this.name);
+ this.event.emit(this.message);
}
}
}
@@ -13491,15 +13491,15 @@ import { Output, EventEmitter, Component, Input } from \\"@angular/core\\";
export default class MyBasicOutputsComponent {
@Input() message!: any;
- @Output() onMessage = new EventEmitter();
- @Output() onEvent = new EventEmitter();
+ @Output() message = new EventEmitter();
+ @Output() event = new EventEmitter();
name = \\"PatrickJS\\";
ngOnInit() {
if (typeof window !== \\"undefined\\") {
- this.onMessage.emit(this.name);
- this.onEvent.emit(this.message);
+ this.message.emit(this.name);
+ this.event.emit(this.message);
}
}
}
@@ -13535,15 +13535,15 @@ import { CommonModule } from \\"@angular/common\\";
export default class MyBasicOutputsComponent {
@Input() message!: any;
- @Output() onMessage = new EventEmitter();
- @Output() onEvent = new EventEmitter();
+ @Output() message = new EventEmitter();
+ @Output() event = new EventEmitter();
name = \\"PatrickJS\\";
ngOnInit() {
if (typeof window !== \\"undefined\\") {
- this.onMessage.emit(this.name);
- this.onEvent.emit(this.message);
+ this.message.emit(this.name);
+ this.event.emit(this.message);
}
}
}
@@ -20404,7 +20404,7 @@ const defaultProps = {
-
+
{{buttonText}}
@@ -20426,7 +20426,7 @@ export default class Button {
@Input() text!: ButtonProps[\\"text\\"] = defaultProps[\\"text\\"];
@Input() buttonText!: ButtonProps[\\"buttonText\\"];
- @Output() onClick = new EventEmitter();
+ @Output() click = new EventEmitter();
@ViewChild(\\"elRef0\\") elRef0!: ElementRef;
@ViewChild(\\"elRef1\\") elRef1!: ElementRef;
@@ -20542,7 +20542,7 @@ const defaultProps = {
-
+
{{buttonText}}
@@ -20566,7 +20566,7 @@ export default class Button {
@Input() text!: ButtonProps[\\"text\\"] = defaultProps[\\"text\\"];
@Input() buttonText!: ButtonProps[\\"buttonText\\"];
- @Output() onClick = new EventEmitter();
+ @Output() click = new EventEmitter();
@ViewChild(\\"elRef0\\") elRef0!: ElementRef;
@ViewChild(\\"elRef1\\") elRef1!: ElementRef;
@@ -20673,7 +20673,7 @@ const defaultProps = {
-
+
{{text}}
@@ -20694,7 +20694,7 @@ export default class Button {
defaultProps[\\"openLinkInNewTab\\"];
@Input() text!: ButtonProps[\\"text\\"] = defaultProps[\\"text\\"];
- @Output() onClick = new EventEmitter();
+ @Output() click = new EventEmitter();
@ViewChild(\\"elRef0\\") elRef0!: ElementRef;
@ViewChild(\\"elRef1\\") elRef1!: ElementRef;
@@ -20806,7 +20806,7 @@ const defaultProps = {
-
+
{{text}}
@@ -20829,7 +20829,7 @@ export default class Button {
defaultProps[\\"openLinkInNewTab\\"];
@Input() text!: ButtonProps[\\"text\\"] = defaultProps[\\"text\\"];
- @Output() onClick = new EventEmitter();
+ @Output() click = new EventEmitter();
@ViewChild(\\"elRef0\\") elRef0!: ElementRef;
@ViewChild(\\"elRef1\\") elRef1!: ElementRef;
diff --git a/packages/core/src/generators/angular/index.ts b/packages/core/src/generators/angular/index.ts
index 4e19b83b26..e3239fa385 100644
--- a/packages/core/src/generators/angular/index.ts
+++ b/packages/core/src/generators/angular/index.ts
@@ -37,7 +37,7 @@ import { BaseHook, MitosisComponent } from '@/types/mitosis-component';
import { Binding, MitosisNode, checkIsForNode } from '@/types/mitosis-node';
import { TranspilerGenerator } from '@/types/transpiler';
import { flow, pipe } from 'fp-ts/lib/function';
-import { isString, kebabCase, uniq } from 'lodash';
+import { camelCase, isString, kebabCase, uniq } from 'lodash';
import traverse from 'neotraverse/legacy';
import { format } from 'prettier/standalone';
import isChildren from '../../helpers/is-children';
@@ -722,6 +722,10 @@ const classPropertiesPlugin = () => ({
},
});
+export function removeOnFromAngularOutputEvent(outputName: string): string {
+ return outputName.startsWith('on') ? camelCase(outputName.substring(2)) : camelCase(outputName);
+}
+
// if any state "property" is trying to access state.* or props.*
// then we need to move them to onInit where they can be accessed
const transformState = (json: MitosisComponent) => {
@@ -865,13 +869,16 @@ export const componentToAngular: TranspilerGenerator =
props.delete(variableName);
});
- const outputs = outputVars.map((variableName) => {
+ const outputs = outputVars.map((outputName) => {
if (options?.experimental?.outputs) {
- return options?.experimental?.outputs(json, variableName);
+ return options?.experimental?.outputs(json, outputName);
}
- return `@Output() ${variableName} = new EventEmitter()`;
+
+ return `@Output() ${removeOnFromAngularOutputEvent(outputName)} = new EventEmitter()`;
});
+ outputs.forEach(console.log);
+
const domRefs = getRefs(json);
const jsRefs = Object.keys(json.refs).filter((ref) => !domRefs.has(ref));
const componentsUsed = Array.from(getComponentsUsed(json)).filter((item) => {
diff --git a/packages/core/src/helpers/strip-state-and-props-refs.ts b/packages/core/src/helpers/strip-state-and-props-refs.ts
index b93a804d86..4122f887fc 100644
--- a/packages/core/src/helpers/strip-state-and-props-refs.ts
+++ b/packages/core/src/helpers/strip-state-and-props-refs.ts
@@ -1,3 +1,4 @@
+import { removeOnFromAngularOutputEvent } from '@/generators/angular';
import { replacePropsIdentifier, replaceStateIdentifier } from './replace-identifiers';
export type StripStateAndPropsRefsOptions = {
@@ -60,7 +61,7 @@ export const DO_NOT_USE_VARS_TRANSFORMS = (
outputVars?.forEach((_var) => {
// determine expression edge cases onMessage( to this.onMessage.emit(
const regexp = '(^|\\s|;|\\()(props\\.?)' + _var + '\\(';
- const replacer = '$1' + context + _var + '.emit(';
+ const replacer = '$1' + context + removeOnFromAngularOutputEvent(_var) + '.emit(';
newCode = newCode.replace(new RegExp(regexp, 'g'), replacer);
});
diff --git a/packages/core/src/parsers/angular.ts b/packages/core/src/parsers/angular.ts
index 26229fa8e3..43d981319a 100644
--- a/packages/core/src/parsers/angular.ts
+++ b/packages/core/src/parsers/angular.ts
@@ -95,7 +95,7 @@ const angularTemplateNodeToMitosisNode = (
});
}
for (const output of node.outputs) {
- bindings['on' + capitalize(output.name)] = createSingleBinding({
+ bindings[capitalize(output.name)] = createSingleBinding({
code: transformBinding(
(output.handler as ASTWithSource)
.source! // TODO: proper reference replace
From 44518d4b64d80cf28dc17e54b865a4d41b0464b3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20Wei=C3=9F?=
<7667003+bastiW@users.noreply.github.com>
Date: Thu, 26 Sep 2024 13:56:22 +0200
Subject: [PATCH 2/5] Fix angular event handling (#2)
* wip: remove on from output variables
* remove on also on emit event
* wip on test
* add event child props
* add e2e test
* Event listener e2e test
* clean up
* add changeset
---
.changeset/six-ghosts-exercise.md | 5 +++++
packages/core/src/generators/angular/index.ts | 2 --
2 files changed, 5 insertions(+), 2 deletions(-)
create mode 100644 .changeset/six-ghosts-exercise.md
diff --git a/.changeset/six-ghosts-exercise.md b/.changeset/six-ghosts-exercise.md
new file mode 100644
index 0000000000..d1d7783f97
--- /dev/null
+++ b/.changeset/six-ghosts-exercise.md
@@ -0,0 +1,5 @@
+---
+'@builder.io/mitosis': minor
+---
+
+Remove on prefix on angulare event emits to be aligned with Angular Style Rule 05-16: Don't Prefix Output Properties
diff --git a/packages/core/src/generators/angular/index.ts b/packages/core/src/generators/angular/index.ts
index e3239fa385..7d95f85b22 100644
--- a/packages/core/src/generators/angular/index.ts
+++ b/packages/core/src/generators/angular/index.ts
@@ -877,8 +877,6 @@ export const componentToAngular: TranspilerGenerator =
return `@Output() ${removeOnFromAngularOutputEvent(outputName)} = new EventEmitter()`;
});
- outputs.forEach(console.log);
-
const domRefs = getRefs(json);
const jsRefs = Object.keys(json.refs).filter((ref) => !domRefs.has(ref));
const componentsUsed = Array.from(getComponentsUsed(json)).filter((item) => {
From 74d0deb23cd7cac3ac91dec0746c9373e748228f Mon Sep 17 00:00:00 2001
From: Sebastian Weiss <7667003+bastiW@users.noreply.github.com>
Date: Thu, 26 Sep 2024 21:10:14 +0200
Subject: [PATCH 3/5] fix event emitters
---
packages/core/src/generators/angular/index.ts | 26 +++++++++++++++----
packages/core/src/generators/react/blocks.ts | 2 +-
.../src/helpers/strip-state-and-props-refs.ts | 5 ++--
3 files changed, 24 insertions(+), 9 deletions(-)
diff --git a/packages/core/src/generators/angular/index.ts b/packages/core/src/generators/angular/index.ts
index 7d95f85b22..21b991459e 100644
--- a/packages/core/src/generators/angular/index.ts
+++ b/packages/core/src/generators/angular/index.ts
@@ -239,6 +239,22 @@ const stringifyBinding =
}
};
+export const replaceOutputEmits = (code?: string, outputEventEmitters?: string[]): string => {
+ let newCode = code || '';
+
+ if (!outputEventEmitters?.length) {
+ return newCode;
+ }
+
+ outputEventEmitters?.forEach((_var) => {
+ const regexp = '(^|\\s|;|\\()(props\\.?)' + _var + '\\(';
+ const replacer = '$1this.' + removeOnFromAngularOutputEvent(_var) + '.emit(';
+ newCode = newCode.replace(new RegExp(regexp, 'g'), replacer);
+ });
+
+ return newCode;
+};
+
const handleNgOutletBindings = (node: MitosisNode, options: ToAngularOptions) => {
let allProps = '';
for (const key in node.properties) {
@@ -558,9 +574,9 @@ const processAngularCode =
DO_NOT_USE_VARS_TRANSFORMS(code, {
contextVars,
domRefs,
- outputVars,
stateVars,
}),
+ (newCode) => replaceOutputEmits(newCode, outputVars),
(newCode) => stripStateAndPropsRefs(newCode, { replaceWith }),
);
@@ -869,11 +885,11 @@ export const componentToAngular: TranspilerGenerator =
props.delete(variableName);
});
- const outputs = outputVars.map((outputName) => {
+ // Building the @Output() EventEmitters
+ const outputEvents = outputVars.map((outputName) => {
if (options?.experimental?.outputs) {
return options?.experimental?.outputs(json, outputName);
}
-
return `@Output() ${removeOnFromAngularOutputEvent(outputName)} = new EventEmitter()`;
});
@@ -997,7 +1013,7 @@ export const componentToAngular: TranspilerGenerator =
Boolean(injectables.length) || dynamicComponents.size || refsForObjSpread.size;
const angularCoreImports = [
- ...(outputs.length ? ['Output', 'EventEmitter'] : []),
+ ...(outputEvents.length ? ['Output', 'EventEmitter'] : []),
...(options?.experimental?.inject ? ['Inject', 'forwardRef'] : []),
'Component',
...(domRefs.size || dynamicComponents.size || refsForObjSpread.size
@@ -1046,7 +1062,7 @@ export const componentToAngular: TranspilerGenerator =
})
.join('\n')}
- ${outputs.join('\n')}
+ ${outputEvents.join('\n')}
${Array.from(domRefs)
.map(
diff --git a/packages/core/src/generators/react/blocks.ts b/packages/core/src/generators/react/blocks.ts
index e31205a0ac..9dd8471f85 100644
--- a/packages/core/src/generators/react/blocks.ts
+++ b/packages/core/src/generators/react/blocks.ts
@@ -290,7 +290,7 @@ export const blockToReact = (
if (json.bindings[key]?.type === 'spread') {
str += ` {...(${value})} `;
} else if (key.startsWith('on')) {
- const { arguments: cusArgs = ['event'] } = json.bindings[key]!;
+ const { arguments: cusArgs = [] } = json.bindings[key]!;
const eventName = options.type === 'native' ? NATIVE_EVENT_MAPPER[key] || key : key;
str += ` ${eventName}={(${cusArgs.join(',')}) => ${updateStateSettersInCode(
useBindingValue,
diff --git a/packages/core/src/helpers/strip-state-and-props-refs.ts b/packages/core/src/helpers/strip-state-and-props-refs.ts
index 4122f887fc..f831ddce0b 100644
--- a/packages/core/src/helpers/strip-state-and-props-refs.ts
+++ b/packages/core/src/helpers/strip-state-and-props-refs.ts
@@ -1,4 +1,3 @@
-import { removeOnFromAngularOutputEvent } from '@/generators/angular';
import { replacePropsIdentifier, replaceStateIdentifier } from './replace-identifiers';
export type StripStateAndPropsRefsOptions = {
@@ -50,7 +49,7 @@ export type DO_NOT_USE_ARGS = {
* Do not use these anywhere. We are migrating to AST transforms and should avoid Regex String.replace() as they are
* very brittle.
*
- * If you need to re-use a part of this, re-create it as an AST tranform first.
+ * If you need to re-use a part of this, re-create it as an AST transform first.
*/
export const DO_NOT_USE_VARS_TRANSFORMS = (
newCode: string,
@@ -61,7 +60,7 @@ export const DO_NOT_USE_VARS_TRANSFORMS = (
outputVars?.forEach((_var) => {
// determine expression edge cases onMessage( to this.onMessage.emit(
const regexp = '(^|\\s|;|\\()(props\\.?)' + _var + '\\(';
- const replacer = '$1' + context + removeOnFromAngularOutputEvent(_var) + '.emit(';
+ const replacer = '$1' + context + _var + '.emit(';
newCode = newCode.replace(new RegExp(regexp, 'g'), replacer);
});
From e7a93f1130a3f84d3535b3a340e721ff1f823214 Mon Sep 17 00:00:00 2001
From: Sebastian Weiss <7667003+bastiW@users.noreply.github.com>
Date: Fri, 27 Sep 2024 10:49:59 +0200
Subject: [PATCH 4/5] rename function for clarity
---
packages/core/src/generators/angular/index.ts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/packages/core/src/generators/angular/index.ts b/packages/core/src/generators/angular/index.ts
index 21b991459e..4ecf128f43 100644
--- a/packages/core/src/generators/angular/index.ts
+++ b/packages/core/src/generators/angular/index.ts
@@ -239,7 +239,7 @@ const stringifyBinding =
}
};
-export const replaceOutputEmits = (code?: string, outputEventEmitters?: string[]): string => {
+export const stripOutputEmits = (code?: string, outputEventEmitters?: string[]): string => {
let newCode = code || '';
if (!outputEventEmitters?.length) {
@@ -576,7 +576,7 @@ const processAngularCode =
domRefs,
stateVars,
}),
- (newCode) => replaceOutputEmits(newCode, outputVars),
+ (newCode) => stripOutputEmits(newCode, outputVars),
(newCode) => stripStateAndPropsRefs(newCode, { replaceWith }),
);
From 603bf045e1c19255af1cdf6e4fa11ca1b3bbd9f9 Mon Sep 17 00:00:00 2001
From: Sebastian Weiss <7667003+bastiW@users.noreply.github.com>
Date: Fri, 27 Sep 2024 10:57:53 +0200
Subject: [PATCH 5/5] add changeset for react
---
.changeset/perfect-tigers-eat.md | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 .changeset/perfect-tigers-eat.md
diff --git a/.changeset/perfect-tigers-eat.md b/.changeset/perfect-tigers-eat.md
new file mode 100644
index 0000000000..1d438dbd8a
--- /dev/null
+++ b/.changeset/perfect-tigers-eat.md
@@ -0,0 +1,5 @@
+---
+'@builder.io/mitosis': patch
+---
+
+React: Fix type error when emitting an event without data (onSomeEvent: () => void; type will now have correct binding in the parent without unnecesarry undefined event parameter)