Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1e6faad

Browse files
crisbetoalxhub
authored andcommitted
fix(compiler-cli): correctly parse event name in HostListener (#60561)
Fixes that we weren't accounting for targeted events when creating the AST for `@HostListener`-decorated members. PR Close #60561
1 parent 7e03af8 commit 1e6faad

File tree

2 files changed

+44
-3
lines changed

2 files changed

+44
-3
lines changed

‎packages/compiler-cli/src/ngtsc/typecheck/src/host_bindings.ts‎

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -387,14 +387,31 @@ function createNodeFromListenerDecorator(
387387

388388
const callNode = new Call(span, nameSpan, receiver, argNodes, span);
389389
const eventNameNode = args[0];
390-
const [eventName, phase] = eventNameNode.text.split('.');
390+
let type: ParsedEventType;
391+
let eventName: string;
392+
let phase: string | null;
393+
let target: string | null;
394+
395+
if (eventNameNode.text.startsWith('@')) {
396+
const parsedName = parser.parseAnimationEventName(eventNameNode.text);
397+
type = ParsedEventType.Animation;
398+
eventName = parsedName.eventName;
399+
phase = parsedName.phase;
400+
target = null;
401+
} else {
402+
const parsedName = parser.parseEventListenerName(eventNameNode.text);
403+
type = ParsedEventType.Regular;
404+
eventName = parsedName.eventName;
405+
target = parsedName.target;
406+
phase = null;
407+
}
391408

392409
listeners.push(
393410
new TmplAstBoundEvent(
394411
eventName,
395-
eventName.startsWith('@') ? ParsedEventType.Animation : ParsedEventType.Regular,
412+
type,
396413
callNode,
397-
null,
414+
target,
398415
phase,
399416
createSourceSpan(decorator),
400417
createSourceSpan(decorator),

‎packages/compiler-cli/test/ngtsc/host_bindings_type_check_spec.ts‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,30 @@ runInEachFileSystem(() => {
257257
expect(getDiagnosticSourceCode(diags[0])).toBe('$event');
258258
});
259259

260+
it('should check @HostListener with a target', () => {
261+
env.write(
262+
'test.ts',
263+
`
264+
import {Component, HostListener} from '@angular/core';
265+
266+
@Component({
267+
template: '',
268+
selector: 'button[foo]',
269+
})
270+
export class Comp {
271+
@HostListener('document:click', ['$event']) handleEvent(event: KeyboardEvent) {}
272+
}
273+
`,
274+
);
275+
276+
const diags = env.driveDiagnostics();
277+
expect(diags.length).toBe(1);
278+
expect((diags[0].messageText as ts.DiagnosticMessageChain).messageText).toBe(
279+
`Argument of type 'MouseEvent' is not assignable to parameter of type 'KeyboardEvent'.`,
280+
);
281+
expect(getDiagnosticSourceCode(diags[0])).toBe('$event');
282+
});
283+
260284
it('should check host animation event listeners', () => {
261285
env.write(
262286
'test.ts',

0 commit comments

Comments
 (0)