Skip to content

Vue.extend alters default class and icons #12777

Open
@Liam44

Description

@Liam44

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 :/

Activity

vivipure

vivipure commented on Sep 13, 2022

@vivipure

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

yyx990803

yyx990803 commented on Oct 11, 2022

@yyx990803
Member

Your reproduction isn't runnable and therefore doesn't really "reproduce" the problem, and seems to be quite different from your other code snippets. Please provide a reproduction that we can actually run and debug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @yyx990803@vivipure@Liam44

        Issue actions

          Vue.extend alters default class and icons · Issue #12777 · vuejs/vue