[Vuejs]-Cancel property update in vue component

0πŸ‘

βœ…

Ok, based on the answer of @Estradiaz, Ifound a solution.
In the mounted() of the component I loop through all properties of the user to make a copy.
On cancel, I copy these props back to the user object.

export default {
  props: ["user"],
  data: () => ({
    initUser: {}
  }),
  mounted() {
    for (const p in this.user) {
      this.initUser[p] = this.user[p];
    }
  },
  methods: {
    submit() {
      this.isDirty = false;
      this.$emit("formIsSubmitted", true);
    },
    cancel() {
      for (const p in this.user) {
        this.user[p] = this.initUser[p];
      }
      this.$emit("formIsSubmitted", `false);
    }
  }
};

0πŸ‘

Inside of created I would recommend creating a variable userForm that gets set to user that the component references. Then when you submit you can just reset userForm as it’s not a prop.

0πŸ‘

You could do something like this

<template>
  <form>

     ... fields to update user property ...

    <button class="btn btn-primary" :disabled="!isDirty" @click.prevent="submit">Submit</button>
    <button class="btn btn-default" @click.prevent="user={}">Cancel</button>
  </form>
</template>

<script>
export default {
  mounted(){
    this.user = this.userObj;
  },
  data(){
     return {
         user: {},
     }
  },
  props: ["userObj"],
  methods: {
    submit() {
      this.$emit("formIsSubmitted", this.user);
    },
  }
};
</script>

0πŸ‘

So basically you want to prevent mutating passed props references.

One aproach is to use computed getter/setter:

...
props: ["user],
data(){return {
  [propname + '_']: ""
}.
computed: {
  [propname]: {
    get(){
       return this[propname + '_'] || this.user[propname]
       // or call cancel in mounted and just 
       return this[propname + '_']
    },
    set(value){
       this[propname + '_'] = value
    }
  }
}
...
cancel(){
   this[propname] = this.user[propname]
}

ofc one can loop asuming this equals flattening and copying:

created(){
  this.cancel()
}
props: ["user"]
data(){return {flatcopy: {}}}
cancel(){
  Object.entries(this.user)
  .forEach(([key,value]) => this.$set(this.flatcopy, key, value)
}

or kind of mixin style (untested but i think should work this way):

function mixin(propname){
return {
...
mounted(){
  if(this.cancel && typeof this.cancel == "function"){
     const cancel = this.cancel.bind(this)
     this.cancel = ()=> {

         this[propname] = this.user[propname]
         cancel()
     }
   } else {
         this.$set(this, cancel, (()=>{this[propname] = this.user[propname]}))
   }
}
props: ["user],
data(){return {
  [propname + '_']: ""
}.
computed: {
  [propname]: {
    get(){
       return this[propname + '_'] || this.user[propname]
       // or call cancel in mounted and just 
       return this[propname + '_']
    },
    set(value){
       this[propname + '_'] = value
    }
  }
}


usage: 
{
  mixins: [mixin('anyname')]
}

Leave a comment