Vue.js/JSX: Dynamic event name

Viewed 1093

I am writing a Vue.js component. The component renders an <input> element. An event listener is listening to either change or input event, according to the value of a prop.

How to write the render function with JSX?

{
  props: {
    lazy: Boolean,
  },
  render(h) {
    const bindEvent = this.lazy? 'change' : 'input'
    return h('input', {
      attrs: {
        type: 'text',
      },
      on: {
        [bindEvent]: e => this.$emit('update', e.target.value)
      },
    })
  },
}

I want to write something like this:

render(h) {
  const bindEvent = this.lazy? 'change' : 'input'
  return <input
    type='text'
    on={{ [bindEvent]: e => this.$emit('update', e.target.value) }}
  />
}
2 Answers

Solution 1: Adding event listener to each event

render(h) {
  const eventHandler = name =>
    (this.bindEvent === name)? e => this.$emit('update', e.target.value)
    : () => {}
  return <input
    type='text'
    onChange={eventHandler('change')}
    onInput={eventHandler('input')}
  />
}

Solution 2: Adding event listener to VNode

render(h) {
  const eventHandler = name =>
    (this.bindEvent === name)? e => this.$emit('update', e.target.value)
    : () => {}
  const vNode= <input type='text' />
  vNode.data.on = { [this.bindEvent]: e => this.$emit('update', e.target.value) }
  return vNode
}

You're almost there. Just a little tweak, like this.

<input
  type="text"
  v-on="{ [bindEvent]: e => this.$emit('update', e.target.value) }"
/>

See working implementation.

Related