1

I've got some form data that I display using a readonly input that is styled to look like plain text. When users click an edit button, they can then edit the inputs and either save or cancel.

My issue is obviously that when a user clicks cancel, the data they entered into the input remains (even though it isn't saved to the DB). I'm trying to figure out a way to reset the input to its initial data. I'm aware of this answer, but it doesn't seem to work because the data is fetched on creation.

This fiddle is similar except for the fact that the data in the real app comes from an axios call. The equivalent call is essentially:

  fetch() {
      axios.get(this.endpoint)
        .then(({data}) => {
          this.name = data.data;
        });
    }

Annoyingly, the fiddle actually works. However in my actual implementation it doesn't. The only difference with the app is that the data is an array.

How can I make this work?

This fiddle represents what my code actually does.

CircularRecursion
  • 450
  • 1
  • 6
  • 18

2 Answers2

1

In the code:

  data: () => ({
    endpoint: 'https://reqres.in/api/users',
    users: [],
    initialData: []
  }),
  //...
    edit: function(index) {
      this.users[index].disabled = false
      this.initialData = this.users
    },
    reset: function(index) {
      this.users[index].disabled = true
      this.users = this.initialData
    }

Since users and initialData are arrays, you must use index when you access them.

So, at first sight, the change would be from:

  this.initialData = this.users

To

  this.initialData[index] = this.users[index]

But this won't work. Since this.users[index] is an object, whenever you change it, it will change what this.initialData[index] holds, since they are both just pointing to the same object. Another problem is that when you set it like that, the initialData won't be reactive, so you must use Vue.set().

Another thing, since you just want to reset the first_name property (the one you use at <input v-model="user.first_name" >), you should then assign user[].first_name to initialData[index].

Considering those changes to edit(), in the reset() method, the addition of [index] and of the .first_name field are enough. Final code:

edit: function(index) {
  this.users[index].disabled = false
  Vue.set(this.initialData, index, this.users[index].first_name);
},
reset: function(index) {
  this.users[index].disabled = true
  this.users[index].first_name = this.initialData[index]
}

JSFiddle: https://jsfiddle.net/acdcjunior/z60etaqf/28/



Note: If you want to back up the whole user (not just first_name) you will have to clone it. An change the order of the disabled property:

edit: function(index) {
  Vue.set(this.initialData, index, {...this.users[index]});
  this.users[index].disabled = false
},
reset: function(index) {
    Vue.set(this.users, index, this.initialData[index]);
}

JSFiddle here. In the example above the clone is created using the spread syntax.

acdcjunior
  • 132,397
  • 37
  • 331
  • 304
0

Input is immediately updating the model. If you want to do something like edit and save you have to take a copy and edit that. I use lodash clone to copy objects then update the fields back when save is clicked. (of course sending message to server.)

KenF
  • 544
  • 4
  • 14