Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

223
Views
Vue 3: v-model helper is not reactive

I wrote myself a little helper for the vue 3 v-model binding. Strangely it does not work fully reactive. Internal changes get emitted in a correct way, external changes are not recognised. But if I use the same computed function within my component, everything works as expected. How do I write the helper, to be fully reactive?

The helper:

import { computed, SetupContext, WritableComputedRef } from 'vue';

export const vModel = <T>(val: T, context: SetupContext, binding = 'modelValue'): WritableComputedRef<T> =>
    computed({
        get: () => val,
        set: (value) => {
            context.emit(`update:${binding}`, value);
        },
    });

The sfc:

<template>
    <div class="ms-deleteInput">
        <input class="ms-deleteInput__input" :label="label" v-model="inputVal" />
        <button @click="$emit('delete')" />
    </div>
</template>

<script lang="ts">
import { defineComponent, computed } from 'vue';

export default defineComponent({
    name: "deleteInput",
    props: {
        modelValue: {
            type: String,
            required: true,
        },
        label: {
            type: String,
            required: true,
        },
    },
    setup(props, context) {

        // This works
        const inputVal = computed({
            get: () => props.modelValue,
            set: (value) => {
                context.emit(`update:modelValue`, value);
            },
        });

        // This works, but external changes of modelValue prop will not be detected:
        const inputVal = vModel(props.modelValue, context);

        return {
            inputVal,
        };
    },
});
</script>
about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

If you do not pass props to the helper, it won't track the props change in computed property.

Pass props instead of props.modelValue to the helper:

const inputVal = vModel(props, context);

Update the helper:

export const vModel = (props, binding) =>
computed({
    get: () => props.modelValue,
    set: (value) => {
        context.emit(`update:${binding}`, value);
    },
});
about 4 years ago · Juan Pablo Isaza Report

0

Thank you for your answers! It works now with this:

import { computed, SetupContext, WritableComputedRef } from 'vue';

export const vModel = <T>(props: Record<string, T>, context: SetupContext, binding = 'modelValue'): WritableComputedRef<T> =>
    computed({
        get: () => props[binding],
        set: (value) => {
            context.emit(`update:${binding}`, value);
        },
    });

but the typing ist not correct. I get the error:

Argument of type 'Readonly<LooseRequired<Readonly<{ modelValue?: unknown; label?: unknown; } & { modelValue: string; label: string; } & {}> & { [x: string & `on${string}`]: undefined; }>>' is not assignable to parameter of type 'Record<string, string>'.
  'string & `on${string}`' and 'string' index signatures are incompatible.
    Type 'undefined' is not assignable to type 'string'.

I tried severall typings for the props within the function, but they all don't seem to be correct. I could't find a good way of typing within the vue documentation.

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!