Stencil.js – explanation of event listeners Code Answer

Hello Developer, Hope you guys are doing great. Today at Tutorial Guruji Official website, we are sharing the answer of Stencil.js – explanation of event listeners without wasting too much if your time.

The question is published on by Tutorial Guruji team.

Consider the following simple input component:

import { Component, VNode, h, Prop, Host } from '@stencil/core'

@Component({
  tag: 'my-input',
})
export class MyInput {
  @Prop() inputId!: string
  @Prop() label!: string
  @Prop() value: string

  render(): VNode {
    return (
      <Host>
        <label htmlFor={this.inputId}>{this.label}</label>
        <input type="text" id={this.inputId} value={this.value}  />
      </Host>
    )
  }
}

Parent component that renders <my-input> component with couple of event listeners:

import { Component, h, VNode } from '@stencil/core'

@Component({
  tag: 'my-page',
})
export class MyPage {
  private handleInput = (ev: Event) => {
    // this works
    console.log('handle input')
  }

  private handleFocus = (ev: Event) => {
    // this doesn't work
    console.log('handle focus')
  }

  private handleClick = (ev: Event) => {
    // this works
    console.log('handle click')
  }

  private handleBlur = (ev: Event) => {
    // this doesn't work
    console.log('handle blur')
  }

  render(): VNode {
    return (
      <my-input
        label="Label"
        inputId="testId"
        onInput={this.handleInput}
        onFocus={this.handleFocus}
        onClick={this.handleClick}
        onBlur={this.handleBlur}
      />
    )
  }
}

Would someone explain to me please, how it’s possible that some of the listeners actually work and the rest do not?

Answer

The reason the focus and blur event handlers don’t fire is because you’re attaching the listeners to the my-input element and not the actual input element. That means only the listeners of events that bubble will fire (click, input) and the rest (focus, blur) won’t.

One way to enable the use of those non-bubbling events is to proxy them:

export class MyInput {
  @Event() myFocus: EventEmitter<FocusEvent>;

  render() {
    return (
      <Host>
        <label htmlFor={this.inputId}>{this.label}</label>
        <input type="text" id={this.inputId} value={this.value} onFocus={e => this.myFocus.emit(e)} />
      </Host>
    )
  }
}

Here I’ve attached an focus event handler to the input and fire the custom myFocus event which you can listen for from outside the component. You might also want to stop these events from bubbling by changing the decorator to @Listen({ bubbles: false }) myFocus;

This is also how the Ionic Framework (made by the same people as Stencil) does it, see https://github.com/ionic-team/ionic-framework/blob/master/core/src/components/input/input.tsx#L220

We are here to answer your question about Stencil.js – explanation of event listeners - If you find the proper solution, please don't forgot to share this with your team members.

Related Posts

Tutorial Guruji