6

I have this problem: I'm trying to modify one of the object's properties with the value from the input form (<el-input> in the example). Our company stack utilizes VueJs + TS + ElementUI. Unfortunately, it seems that objects' properties cannot be reactive and are in read-only mode. How can I make object properties reactive?

HTML/CSS

<el-input v-model="group.groupDescription" type="textarea"></el-input>

JS:

interface ViewGroupResult {
  id: string;
  groupDescription: string;
}

import Vue from 'vue';
import {Component, Watch} from 'vue-property-decorator';
@Component
apollo: {

  group: {
    query() {
          group(groupId: $groupIdOrSlug) { ... }
        }
    },
    variables() {
      groupId: this.id
    },
    fetchPolicy: 'network-only',
    loadingKey: 'groupLoading'
  },

export default class ViewGroupPage extends Vue implements 
    group: ViewGroupResult | null = null;

When I try to type something in the text area above, the value is never updated for the group object's property group.groupDescription even though it's bound with v-model directive.

Error in event handler for "input": "TypeError: Cannot assign to read only property 'groupDescription' of object '#<Object>'"

Do I misunderstand the way getters/setters are bound to data properties in VueJs, or is this a TypeScript specific problem? Thanks in advance!

kyle
  • 691
  • 1
  • 7
  • 17
Ren
  • 944
  • 1
  • 13
  • 26
  • I actually think that it's possible with ```Vue.set``` but are there maybe other workarounds I'm not aware of? – Ren Feb 17 '19 at 01:26
  • 1
    Before trying to workaround the read only error, I might investigate why that property has been designated as read only. If it's on purpose, then you probably shouldn't be trying to change the property. That might break something somewhere else in the application. If it's just an over-zealous typescript decoration, then change it. – Stephen Thomas Feb 17 '19 at 01:31

1 Answers1

0

In VueJS there is strict parameters blocking developers from modifying props directly. The workaround is to set a data property to the initial value given by the corresponding prop. I.E. given a prop of initialUser we would set a data property of user with it's value set to this.initialUser with this method you'll be able to modify the user variable while still getting the initial value passed to the component via the initialUser prop. Please let me know if you have any questions.

    props: {
        initialUser: {
            type: Object,
            required: true
        }
    },
    data() {
        return {
            user: this.initialUser
        }
    },
  • Having created one more variable doesn't solve the problem unfortunately as it just references it, but the problem remains. I ended up using watcher instead, but I'm still sort of perplexed why it's not so easy to modify object's properties. – Ren Feb 17 '19 at 20:12
  • @Ren Can you add your solution with watchers here? Creating a new variable didn't work for me as well. – Vishnu Dec 10 '21 at 15:01
  • @Ren @vishnu Suggestion: clone the prop-object and use a watcher to watch for eventual changes on the prop-object outside of the component. To change the prop-object from inside of the component, you'll have to emit an event and listen to it in the parent component. You might want to try using the prop-object as a `v-model`, cloning it in the component and emitting an event whenever the clone is modified. – zunnzunn Mar 08 '22 at 13:02