PHilgarth
PHilgarth

Reputation: 285

Vue3 - pass multiple event listeners along with their handlers to child component

in Vue3 I can do the following:

Parent Component:

<ChildComponent :props="{ id: 'the-id', class: 'the-class' }" />

ChildComponent:

<template>
    <input v-bind="props" />
</template>

<script>
export default {
    props: {
        props: { type: Object }
    }
}
</script>

This will result in HTML like this:

<input id="the-id" class="the-class" />

I'm still learning Vue and I was wondering if I could do the same thing with event listeners / handlers.

With reusable components I might need different event listeners / handlers, depending on where I use the component. In one form I might need only an @input="..." in the child component, in another form I might also need an @blur="..." or I might not need an event listener at all.

Is it possible to do something similar to this?

ParentComponent:

<ChildComponent :events="{ input: function() { alert('input!'); }, blur: function() { alert('blur!'); } } />

ChildComponent:

<template>
    <input @events />
</template>

<script>
export default {
    props: {
        props: { type: Object }
    }
}
</script>

Thank you ;)

Upvotes: 4

Views: 9007

Answers (3)

lee whitbeck
lee whitbeck

Reputation: 458

My recommendation would be to define the different events though Vue's Custom Events; The custom events would allow the users of the component to choose which event to subscribe to and handle it accordingly.

https://v2.vuejs.org/v2/guide/components-custom-events.html

Upvotes: 0

Thomas
Thomas

Reputation: 7078

You can also do something similar like you did with the props, by passing an object to v-on:

<input v-on="{ input: doThis, blur: doThat }"></button>

See here: https://v3.vuejs.org/api/directives.html#v-on

Upvotes: 7

tony19
tony19

Reputation: 138266

The root element of a component automatically inherits all non-prop attributes (including event listeners) applied to the component from the parent. So if <input> were really at the root in ChildComponent, you wouldn't need to declare anything, and you could simply apply attributes to ChildComponent as if it were the input itself:

<ChildComponent id="the-id" class="the-class" @blur="onBlur" />

demo 1

However, this will break as soon as you add another element to ChildComponent because <input> would no longer be the root. It also would be a problem if you wanted to switch the root element (e.g., a <label> that wraps the <input>).

To disable automatic attribute inheritance, allowing control of where to apply the inherited attributes, set inheritAttrs: false in component options. (This doesn't need to be disabled when there are multiple root nodes, as it only applies for single-root components.) Then manually v-bind the $attrs prop to any element within:

<template>
  <label>My input: <input v-bind="$attrs"></label>
</template>

<script>
export default {
  inheritAttrs: false,
}
</script>

demo 2

Upvotes: 4

Related Questions