Vue.extend alters default class and icons

This issue has been tracked since 2022-09-10.

Version

2.7.0

Reproduction link

codesandbox.io

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 standard v-radio-group behaviour (I printed out in console and the created object radioButton 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 :/

vivipure wrote this answer on 2022-09-13

Your Vue version in codesandbox is 3.2.39. Vue 3 does not support Vue.extend, you can use createApp .

More Details About Repo
Owner Name vuejs
Repo Name vue
Full Name vuejs/vue
Language TypeScript
Created Date 2013-07-29
Updated Date 2022-10-03
Star Count 199758
Watcher Count 6095
Fork Count 32874
Issue Count 590

YOU MAY BE INTERESTED

Issue Title Created Date Updated Date