I'm making an InputWrapper component used for decorating some BootstrapVue input components. The point is to automatically handle validation states, messages, styling, etc. (not shown in the example bellow) around a given input.
I would like to dynamically "forward" v-model. The problem comes when the wrapped component uses custom model attribute and update event for two way binding.
The main idea goes as follow.
InputWrapper.Vue
<template>
<div>
<slot v-bind="wrappedBindings"></slot>
</div>
</template>
<script>
export default {
props: {
value: {required: true}
},
methods: {
onInput($event){
this.$emit('input', $event);
}
},
computed: {
wrappedBindings(){
return {
attrs: {
value: this.value
},
on: {
input: $event => this.onInput($event),
'update:value': $event => this.onInput($event)
}
}
}
}
}
</script>
Usage
<div>
<input-wrapper v-model="selectModel" v-slot="{attrs, on}">
<!-- v-model of b-form-select is :value and @input so this works -->
<b-form-select v-bind="attrs" v-on="on" ...other stuff...></b-form-select>
</input-wrapper>
<input-wrapper v-model="inputModel" v-slot="{attrs, on}">
<!-- v-model of b-form-input is :value and @update (not @update:value or @input) so this does not work -->
<b-form-input v-bind="attrs" v-on="on" ...other stuff...></b-form-input>
</input-wrapper>
<input-wrapper v-model="checkModel" v-slot="{attrs, on}">
<!-- v-model of b-form-checkbox is :checked (not :value) and @input so this does not work -->
<b-form-checkbox v-bind="attrs" v-on="on" ...other stuff...></b-form-checkbox>
</input-wrapper>
</div>
My current and unsatisfactory solution
<div>
<input-wrapper v-model="inputModel" v-slot="{attrs, on}">
<b-form-input v-bind="attrs" v-on="on" @update="on.input"
...other stuff...></b-form-input>
</input-wrapper>
<input-wrapper v-model="checkModel" v-slot="{attrs, on}">
<b-form-checkbox v-bind="attrs" v-on="on" :checked="attrs.value"
...other stuff...></b-form-checkbox>
</input-wrapper>
</div>
This solution allows me to do what I want but it's longer to implement and you always need the BootstrapVue documentation close by.
Another solution would be to make a custom component for every BsVue input, but I would also need to forward every attribute and event to the custom component. There are many reasons for not doing this but mainly it would be harder to maintain.
My question is the following: How can I use v-bind="attrs" and v-on="on" to dynamically bind any custom v-model attribute and event without knowing them beforehand?