skip to Main Content

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


  1. 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:

    1. Define your HostListener in your app.component.ts for example.

    2. Define a Observable to send the key events in your service. keyEvents$ = new BehaviorSubject(null)

    3. In app.component.ts, with you HostListener, use your service and add keyEvents$.next(event)

    4. 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(...)

    Login or Signup to reply.
  2. Use Angular Renderer2 to keep your approach.

    Example:

    private renderer: Renderer2;
    private unlistener: () => void;
    
    public constructor(private rendererFactory: RendererFactory2, private readonly dialogService: DialogService, private readonly userAgent: UserAgentService) {
    
      // in a service, you need to use renderer factory
      this.renderer = this.rendererFactory.createRenderer(null, null);
      
      // start listen and store the "unlisten" function
      this.unlistener = this.renderer.listen('document', 'keydown.escape', () => {
          // put here your logic
          console.log(event);
      }); 
    
    }
    
    ngOnDestroy() {
      // will unlisten on service destroy (or change it according to your requirements)
      this.unlistener();
    
    }
    

    See:

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search