4

I created an Input web component with Stencil:

...
export class Input {
    @Prop({ mutable: true }) value: string;
    @Event() changed: EventEmitter<KeyboardEvent>;

    private handleChange (e) {
        this.value = e.target?.value;
        this.changed.emit(e);
    }

    render() {
        return (
            <div class="inputContainer">
                <input  
                    type="text"
                    value={this.value}
                    onInput={this.handleChange}
                />
            </div>
        )
    }
}

Then after trying to use it inside React jsx file, onChanged does not call console.log

...

function App() {
  return (
    <div className="App">
      // does not call console.log
      <ui-input onChanged={(e) => console.log(e)}/>
    </div>
  );
}


As I've read so far it's because React uses the synthetic event instead of Dom events.

Is there any way to use Dom events within JSX element?

Simon Hänisch
  • 4,740
  • 2
  • 30
  • 42
Mammad Mammadli
  • 310
  • 1
  • 2
  • 9

2 Answers2

5

You would have to manually attach the event listener using the DOM API, for example:

document.querySelector('ui-input').addEventListener('changed', console.log)

(You can also use the ref prop to get a reference to the DOM element which is probably more robust.)

You have another option though, and that's to use the stencil-ds-plugins, specifically the @stencil/react-output-target npm package. When you build your component/library, the output target will generate all the necessary bindings (props, custom events, etc.) for you, and you'll be able to use your component as a react component. The only available docs so far ar in the readme: https://github.com/ionic-team/stencil-ds-plugins#react.

Simon Hänisch
  • 4,740
  • 2
  • 30
  • 42
0

You need to bind the current context to the method.

Check Event emit error for more explanation

...
export class Input {
    constructor() {
       this.handleChange = this.handleChange.bind(this);
    }

    @Prop({ mutable: true }) value: string;
    @Event() changed: EventEmitter<KeyboardEvent>;

    private handleChange (e) {
        this.value = e.target?.value;
        this.changed.emit(e);
    }

    render() {
        return (
            <div class="inputContainer">
                <input  
                    type="text"
                    value={this.value}
                    onInput={this.handleChange}
                />
            </div>
        )
    }
}
Paul Taiwo
  • 71
  • 5