0

I have a component called Input.vue, which basically prints label and and input of some type. It looks like this:

<template>
    <div class="form-element">
        <label :for="inputId" :class="['form-element-title', { 'js-focused': focused }]">{{ label }}</label>
        <input :disabled="!canEdit" :type="inputType" :id="inputId" :name="inputName" v-model="inputData" :placeholder="placeholder" @focus="focused = true" @blur="focused = false">
    </div>
</template>

<script lang="ts">
    import { Component, Prop, Vue } from 'vue-property-decorator';

    @Component
    export default class Input extends Vue {
        @Prop({ default: () => {} }) inputId!: string
        @Prop({ default: () => {} }) inputType!: string
        @Prop({ default: () => {} }) inputName!: string
        @Prop({ default: () => {} }) label!: string
        @Prop({ default: () => {} }) placeholder!: string
        @Prop({ default: () => {} }) data!: string
        @Prop({ default: () => true }) canEdit!: boolean

        private inputData = this.data;
        private focused = false
    }
</script>

It's being called from another component like this:

<input-component inputId="formDiscountName"
                 inputType="text"
                 inputName="discountName"
                 :label="translations['name']"
                 :placeholder="translations['name']"
                 :data="discount.name"
/>

Now the problem is that if I enter any data in this input, discount.name doesn't get any value set, because inside input-component it's instantly assigned to inputData variable and data property doesn't get any update. Now I can't mutate data property itself because of the Vue warning.

What should I do? I tried to use computed properties but I am not sure what get and set functions should look like.

One thing I can think of is to use computed property and emit an update on set function:

get inputData() {
    return this.data;
}

set inputData(value: string) {
    this.$root.$emit('inputUpdate', {'inputName' : this.inputName, 'inputValue' : value});
}

But emit doesn't look very clean method. Is there anything better?

1 Answer 1

1

You can add a watcher on the inputData. Post that there are couple of ways that discount.name can be updated.

  1. Either emit the inputData value from the watcher and add a handler in parent component

Or

  1. Not sure what is your usecase here but instead of passing discount.name, you can pass the discount object and then modify the name property of the object - there won't be any warning since you are modifying a property of an object.
Sign up to request clarification or add additional context in comments.

1 Comment

Actually the second option kinda worked. I want this Input component to be used by another multiple components, but if I pass the name of the property it looks like I can set the model like this: v-model="inputData[inputName]". Thank you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.