Reputation: 57
Is it possible to set dynamic on event in VueJS? I try to build a dynamic form as component with inputs that can listen on everything. Here an example:
import Vue from 'vue';
let formItems = {
{type: 'checkbox', id: 'some-id', on:'change', model: 'someId'},
{type: 'url', id: 'another-id', on:'keyup', model:'anotherId'},
};
let params = {
someId: true,
anotherId: 'http://www.example.com',
};
new Vue({
el: '#app',
data: {
formItems: formItems,
params: params,
},
methods: {
checkInputParams(e) {
e.preventDefault();
// Do some stuff.
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.js"></script>
<div id="app">
<div class="form-group" v-for="item in formItems">
<input type="checkbox" <!-- Also need a workaround for dynamic type and v-model -->
:id="item.id"
:class="(item.class ? item.class : '')"
:title="(item.title ? item.title : '')"
:placeholder="(item.placeholder ? item.placeholder : '')"
:autocomplete="(item.autocomplete ? item.autocomplete : false)"
:disabled="(item.disabled ? item.disabled : false)"
:max="(item.max ? item.max : '')"
:min="(item.min ? item.min : '')"
:maxlength="(item.maxLength ? item.maxLength : '')"
:multiple="(item.multiple ? item.multiple : '')"
:name="(item.name ? item.name : '')"
:readonly="(item.readonly ? item.readonly : false)"
:required="(item.required ? item.required : false)"
v-on="{{ item.on }}:checkInputParams" <!-- Here I try the dynamic v-on -->
v-model="params[item.model]"/>
</div>
</div>
Is it possible to set a dynamic v-on event like v-on="<variable>:<function>"
?
Upvotes: 5
Views: 10196
Reputation: 2538
From Vue 2.4.0+, v-on
accepts an object syntax
Refer this documentation
<button v-on="{ mousedown: doThis, mouseup: doThat }"></button>
Upvotes: 16
Reputation: 89472
In Vue 3, you can pass a dynamic argument to v-on
with square brackets.
<input @[item.on]="checkInputParams" />
Upvotes: 1
Reputation: 753
Check out this custom input component. I'm also using event modifiers(kind of) dynamically through the callback event function. I'm passing the event name and callback to the custom component.
BaseFormTextInput.vue
<script setup>
import { computed } from 'vue'
const props = defineProps(['modelValue', 'label', 'id', 'type', 'event', 'eventHandler'])
const emit = defineEmits(['update:modelValue'])
const value = computed({
get() {
return props.modelValue
},
set(value) {
emit('update:modelValue', value)
}
})
</script>
<template>
<div class="o-form__textControl">
<label :for="id" class="o-form__label">{{ label }}</label>
<slot name="input">
<input @[event]="eventHandler($event)" :type="type" name="email" :id="id" v-model="value" />
</slot>
</div>
</template>
Parent.vue
<script setup>
import { reactive, ref } from 'vue'
import BaseFormTextInput from '../components/BaseFormTextInput.vue'
const skills = reactive([])
const tempSkill = ref('')
const addSkill = (e) => {
if (e.key === ',' && e.altKey === true) {
if (!skills.includes(this.tempSkill)) {
skills.push(this.tempSkill)
}
this.tempSkill = ''
}
}
</script>
<template>
<BaseFormText
label="skills (press alt + comma to add):"
id="skills"
v-model="registerModel.tempSkill"
:event-handler="addSkill"
event="keyup"
/>
</template.
Upvotes: 0
Reputation: 41
Try:
<button v-on="buttonListeners"></button>
// ...
{
data() {
return {
listeners: {
'mousedown': 'doThis',
},
};
},
computed: {
buttonListeners() {
return Object
.entries(this.listeners)
.reduce((acc, [eventName, methodName]) => ({
...acc,
[eventName]: this[methodName],
}), {});
},
},
};
Upvotes: 0