I have service for dialog
Here it is
@Injectable()
export class HomeDialogService {
public constructor(private readonly dialogService: DialogService, private readonly userAgent: UserAgentService) {}
@HostListener('document:keydown.escape', ['$event']) onKeydownHandler(event: KeyboardEvent) {
console.log(event);
}
public open<TComponentParams, TResult>(
content: Type<DialogBaseComponent<TComponentParams, TResult>>,
params?: TComponentParams,
dialogOptions?: HomeDialogSettings | undefined,
): { dialogRef: DialogRef; result$: Observable<IDialogResult<TResult>> } {
const desktopDialogWidth = dialogOptions.kendoDialogSettings.width ?? DESKTOP_DEFAULT_DIALOG_WIDTH;
const desktopDialogMaxHeight = dialogOptions.kendoDialogSettings.maxHeight ?? DESKTOP_MAX_POPUP_HEIGHT;
const isMobile = this.userAgent.mobile;
const dialogRef = this.dialogService.open({
content,
...dialogOptions.kendoDialogSettings,
width: isMobile ? WIDTH_FULL : desktopDialogWidth,
maxHeight: isMobile ? MOBILE_MAX_POPUP_HEIGHT : desktopDialogMaxHeight,
});
const component = dialogRef.content.instance as DialogBaseComponent<TComponentParams, TResult>;
if (params) {
component.params = params;
}
if (isMobile) {
this.configureDialogStylesForNonDesktop(dialogRef);
}
const result$ = dialogRef.result.pipe(
map((result: DialogCloseResult | TResult) => {
if (result instanceof DialogCloseResult) {
return {
status: DialogResultStatus.Cancel,
};
}
return { status: DialogResultStatus.Ok, data: result };
}),
);
return {
dialogRef,
result$,
};
}
}
I added listener for escape
button click in it and inject it in component like this
export class SdTicketComponent {
@Input()
public ticket!: ServiceDeskTicket;
constructor(
public readonly userAgent: UserAgentService,
public readonly startScreenSdTicketsSectionService: StartScreenSdTicketsSectionService,
private readonly serviceDeskService: ServiceDeskService,
private readonly dialogService: HomeDialogService,
private readonly alertService: AlertService,
) {}
public onTicketClick(): void {
this.dialogService
.open(
SdTicketPopupComponent,
{ ticket: this.ticket },
{ kendoDialogSettings: { title: this.ticket.summary, width: 880, cssClass: 'sd-ticket-popup-wrapper' } },
)
.result$.pipe(
filter(result => result.status === DialogResultStatus.Ok),
map(result => result.data as IServiceDeskIssueRateData),
switchMap(result => this.serviceDeskService.closeTicket(this.ticket, result)),
switchMap(() => this.startScreenSdTicketsSectionService.initSectionData(true)),
untilDestroyed(this),
)
.subscribe(_ => {
this.alertService.showSuccess(`${this.ticket.key} has been closed`);
});
}
}
But when I press escape
key , console not show anything
If I move code for HostListener
to component, everything okay.
How I can make it work from service?
2
Answers
As you mention, the
HostListener
should be defined in a component.If you want to listen to the key events in the whole application, you can do the following:
Define your
HostListener
in yourapp.component.ts
for example.Define a Observable to send the key events in your service.
keyEvents$ = new BehaviorSubject(null)
In
app.component.ts
, with you HostListener, use your service and addkeyEvents$.next(event)
In your component where you want to capture the event, you can import the service and subscribe to the changes.
keyEvents$.pipe(map(event=> event.key ==="escape")).subscribe(...)
Use Angular Renderer2 to keep your approach.
Example:
See: