theberzi
theberzi

Reputation: 2645

Missing required prop: "value" on model/value binding for custom input component in Vue

I followed this guide while trying to make a custom form component in Vue 3 (composition api, script setup mode).

When I load the page containing my component, I get a console warning like this one:

[Vue warn]: Missing required prop: "value" at <SwitchControl key=0 name="question-8" model=undefined ... >

My component (CSS omitted):

<template>
  <input ref="switchElement"
         v-bind="$attrs"
         class="gui-switch"
         @input="value = !value; emit('update:modelValue', value)"
         type="checkbox"
         role="switch"
         :value="value" />
</template>

<script setup lang="ts">
import { defineEmit, defineProps, onMounted, ref } from "vue"


const props = defineProps<{
  value: boolean | undefined,
}>()

const emit = defineEmit<{
  (e: "update:modelValue", value: boolean | undefined): void,
}>()

const switchElement = ref<HTMLInputElement>()

onMounted(() => switchElement.value!.indeterminate = true)
</script>

The page that contains it uses it like so:

<!-- v-for question in questions -->
<switch-control :name="`question-${question.id}`"
             :model="feedbackData[`question-${question.id}`]"
             :id="`question-${question.id}`" />

I've tried various things such as changing the name of the emitted event to input or using v-model instead of :model but I haven't managed to fix this yet and I don't know what else to try.

EDIT: Editing the component to use modelValue thusly:

<template>
  <input ref="switchElement"
         v-bind="$attrs"
         class="gui-switch"
         @input="modelValue = !modelValue; emit('update:modelValue', modelValue)"
         type="checkbox"
         role="switch"
         :value="modelValue" />
</template>

<script setup lang="ts">
import { defineEmit, defineProps, onMounted, ref } from "vue"


const props = defineProps<{
  modelValue: boolean | undefined,
}>()

const emit = defineEmit<{
  (e: "update:modelValue", value: boolean | undefined): void,
}>()

const switchElement = ref<HTMLInputElement>()

onMounted(() => switchElement.value!.indeterminate = true)
</script>

Parent:

<!-- v-for question in questions -->
<switch-control :name="`question-${question.id}`"
             v-model="feedbackData[`question-${question.id}`]"
             :id="`question-${question.id}`" />

Leads to an outright error:

[Vue warn]: Unhandled error during execution of scheduler flush. This is likely a Vue internals bug. Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/vue-next
at <SwitchControl key=0 name="question-8" modelValue=undefined  ... > 

Uncaught (in promise) TypeError: invalid 'instanceof' operand type
    assertType runtime-core.esm-bundler.js:1877
    validateProp runtime-core.esm-bundler.js:1841
    validateProps runtime-core.esm-bundler.js:1817
    initProps runtime-core.esm-bundler.js:1548
    setupComponent runtime-core.esm-bundler.js:6500
    mountComponent runtime-core.esm-bundler.js:4206
    processComponent runtime-core.esm-bundler.js:4182
    patch runtime-core.esm-bundler.js:3791
    mountChildren runtime-core.esm-bundler.js:3975

EDIT2: I managed to zoom in on whereabouts the problem is, but I still can't quite figure out what's happening.

I changed the component so that @input is now @input="emit('update:modelValue', !modelValue)". I'll include the relevant parts of the <script> of the page that includes it:

import SwitchControl from "@/components/SwitchControl.vue"
import type { FeedbackQuestion } from "@/utils/api/story"
import { defineProps, ref } from "vue"


const props = defineProps<{
  questions: {id: number}[],
}>()

const defaultModelValues = {
  // These are hard-coded for debugging, ideally I'd want it to work with an empty initial object
  "question-8": null,
  "question-11": null,
}
const feedbackData = ref<Record<string, any>>(defaultModelValues)

Now the symptoms:

[Vue warn]: Unhandled error during execution of scheduler flush. This is likely a Vue internals bug. Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/vue-next 
  at <SwitchControl modelValue=null onUpdate:modelValue=fn<onUpdateModelValue> name="question-8"  ... >

Uncaught (in promise) TypeError: invalid 'instanceof' operand type
[Vue warn]: Invalid prop: type check failed for prop "modelValue". Expected Boolean, got Null  
  at <SwitchControl modelValue=null onUpdate:modelValue=fn<onUpdateModelValue> name="question-8"  ... >

Upvotes: 3

Views: 14365

Answers (2)

Riki krismawan
Riki krismawan

Reputation: 567

use ref from vue can fix warning message

import { defineStore } from "pinia";
import { ref } from "vue";

export const usePosts = defineStore("posts", {
  state: () => {
    return {
      data: [],
      errors: [],
      title: "",
      content: "",
      image: ref(),
    };
  },
});

vue file

 <q-file color="primary" v-model="postsStore.image" label="Image">
  <template v-slot:prepend>
    <q-icon name="cloud_upload" />
  </template>
 </q-file>

Upvotes: 0

Boussadjra Brahim
Boussadjra Brahim

Reputation: 1

In the child component you should define value as modelValue :

 <input ref="switchElement"
         ...
         :value="modelValue" />
</template>

.....
const props = defineProps<{
  modelValue : boolean | undefined,
}>()

and in parent use v-model instead of :model :

  v-model="feedbackData[`question-${question.id}`]"

Upvotes: 3

Related Questions