Description
Version
2.7.0
Reproduction link
Steps to reproduce
Greetings everyone and congratulations for a great job. Getting inspired by this webpage (https://css-tricks.com/creating-vue-js-component-instances-programmatically), I tried to create and add custom components to one of my templates at runtime.
To sum up, I need to insert at runtime custom components which contain standard vue components (such as v-swith or v-radio-group for example).
Here is what I've done for one of my custom components, containing v-switches:
child .ts file:
export default class CheckboxComponent extends Vue {
@Prop({required: false, type: Boolean, default: null})
public defaultValue: boolean;
@Prop({required: true, type: Number, default: 0})
public id: number;
@Prop({required: true, type: String, default: ""})
public label: string;
public yes: boolean = false;
public no: boolean = false;
child .vue file:
<template>
<v-row dense>
<v-col cols="8">
{{ label }}
</v-col>
<v-col cols="2">
<v-switch
v-model="yes"
label="Yes"
color="success"
/>
</v-col>
<v-col cols="2">
<v-switch
v-model="no"
label="No"
color="red"
/>
</v-col>
</v-row>
</template>
parent .ts file:
let CheckboxClass = Vue.extend(CheckboxComponent);
let checkbox = new CheckboxClass({
propsData: { id: 1, value: null, label: "Some checkbox" }
});
checkbox.$mount();
(this.$refs.container as HTMLElement).appendChild(checkbox.$el);
checkbox.$on("change", this.onCheckboxValueChanged);
And that works perfectly fine: https://i.stack.imgur.com/mRhzS.png
But if I try to do the same with v-radio-groups instead, it goes like this:
child .ts file:
export default class RadioButtonComponent extends Vue {
@Prop({required: false, type: String, default: null})
public defaultValue: string;
@Prop({required: true, type: Number, default: 0})
public id: number;
@Prop({required: true, type: String, default: ""})
public label: string;
@Prop({required: true, type: Array, default: () => []})
public options: string[];
child .vue file:
<template>
<v-row dense>
<v-col cols="6">
{{ label }}
</v-col>
<v-col cols="6">
<v-radio-group
v-model="value"
mandatory
row
>
<v-radio
v-for="(option, index) in options"
:key="index"
:label="option"
:value="option"
/>
</v-radio-group>
</v-col>
</v-row>
</template>
parent .ts file:
let RadioButtonClass = Vue.extend(RadioButtonComponent);
let radioButton = new RadioButtonClass({
propsData: { id: 2, defaultValue: "One", label: "Some radio button", options: ["One", "Two", "Three", "Four"] }
});
radioButton.$mount();
(this.$refs.container as HTMLElement).appendChild(radioButton.$el);
radioButton.$on("change", this.onRadioButtonValueChanged);
but it's then rendered this way: https://i.stack.imgur.com/LX8s2.png
What is expected?
I was expecting the v-radio-boxes to properly be displayed, just as v-switches are.
What is actually happening?
Let me explain what I found out, comparing that result to a "regular" added v-radio-group. It seems that all that's wrong comes from the v-input-selection
styling:
<i aria-hidden="true" class="v-icon notranslate material-icons theme--light accent--text"\>$radioOn</i\>
As you can see $radioOn
stands right in the slot, where it should be empty, plus the class that doesn't seem right as it should either be mdi mdi-radiobox-blank
or mdi mdi-radiobox-marked
whether the option is selected or not.
If I manually edit the style to the correct one, I'll then get https://i.stack.imgur.com/127ff.png
So, my question is:
-
is it a bug in
Vue.extend
that alters standardv-radio-group
behaviour (I printed out in console and the created objectradioButton
already has the wrong values) -
or is it designed to be this way, in order to let the developers customize their component, in which case I'm surely missing something.
I've also tried the same implementation with v-checkbox and gets the same result as with v-radio-group.
I tried to reproduce the development environment in CodeSandbox but didn't manage to get it compiled using Vue 3 :/