Home > OS >  Vue 3 slot props not reactively changing data in parent
Vue 3 slot props not reactively changing data in parent

Time:11-29

I have a slot containing radio buttons in a parent Vue3 component, I'm passing a v-model attribute to these radio buttons and the data model exists in the parent component. However when I change the selected radio button in the slot, the data in the parent component doesn't change.

parent template:

<template>
    <div >
        <div >
            <slot
                :type="type"
            />
        </div>
    </div>
</template>

parent vue:

<script>
    export default {
        data() {
            return {
                type: 'standard',
            }
        },
    }
</script>

slot content:

<parent v-slot="slotProps">
    <div >
        <label>
            <span >Type</span>
        </label>
        <label>
            Standard Model
            <input v-model="slotProps.type" type="radio" name="type" value="standard" required/>
        </label>
        <label>
            Touch Model
            <input v-model="slotProps.type" type="radio" name="type" value="touch" required/>
        </label>
        <label>
            Display Model
            <input v-model="slotProps.type" type="radio" name="type" value="display" required/>
        </label>
    </div>
</parent>

CodePudding user response:

I do not think this is a good idea and this is also not recommended by the Vue team.
Anyway, if you really need to do it, as stated by posva from the Vue team, you can pass a method instead to change the value or you can pass an object and modify a property (keep in mind this is not recommended).

Here is the object way to do it:

Parent:

<template>
  <div >
    <div >
      <slot :myObject="myObject" />
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      myObject: {
        type: "standard",
      },
    };
  },
};
</script>

Slot content:

<parent v-slot="slotProps">
  <div >
    <label>
      <span >Type</span>
    </label>
    <label>
      Standard Model
      <input
        v-model="slotProps.myObject.type"
        type="radio"
        name="type"
        value="standard"
        required
      />
    </label>
    <label>
      Touch Model
      <input
        v-model="slotProps.myObject.type"
        type="radio"
        name="type"
        value="touch"
        required
      />
    </label>
    <label>
      Display Model
      <input
        v-model="slotProps.myObject.type"
        type="radio"
        name="type"
        value="display"
        required
      />
    </label>
  </div>
</parent>


Here is the method way to do it:

Parent:

<template>
  <div>
    <div>
      <slot :type="type" :onTypeChange="onTypeChange" />
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      type: "touch",
    };
  },
  methods: {
    onTypeChange(event) {
      this.type = event.target.value;
    },
  },
};
</script>

Slot content:

<parent v-slot="slotProps">
  <div >
    <label>
      <span >Type</span>
    </label>
    <label>
      Standard Model
      <input
        v-model="slotProps.type"
        type="radio"
        name="type"
        value="standard"
        required
        @change="slotProps.onTypeChange"
      />
    </label>
    <label>
      Touch Model
      <input
        v-model="slotProps.type"
        type="radio"
        name="type"
        value="touch"
        required
        @change="slotProps.onTypeChange"
      />
    </label>
    <label>
      Display Model
      <input
        v-model="slotProps.type"
        type="radio"
        name="type"
        value="display"
        required
        @change="slotProps.onTypeChange"
      />
    </label>
  </div>
</parent>
  • Related