Search code examples
vue.jsgraphqlvue-apollo

Avoid caching problems when creating an edit form with vue-apollo


I'm working on my first vue-apollo project and I'm wondering what's the best way to create an edit form. I can't seem to find any examples online.

Right now I'm querying my user data like this:

export default {
  data() {
    return {
      user: {
        id: '',
        name: '',
        email: '',
      },
    }
  },
  apollo: {
    user: {
      query: USER_QUERY,
    },
  },
}

With a simple form like this:

<form @submit.prevent="submitForm">
  <label>Name</label>
  <input type="text" v-model="user.name" />

  <label>Email</label>
  <input type="text" v-model="user.email" />

  <button type="submit">Submit</button>
  <button type="button" @click="cancel">Cancel</button>
</form>

The problem is that when I edit the form and then close it, my edit is returned by the GraphQL cache when I return to the form. This is because my input is binded directly to the object returned by my GraphQL query with v-model. I can think of a two things to avoid this:

  • Create a copy of the data returned by the query (and call it user and userData?), and bind the v-model to the keys of that object. But it bugs me that I need to create a duplicate variable and have the data in two places.
  • Or disable cache for this GraphQL query altogether.

It feels like I'm missing a more obvious solution. When I was using REST a had a Form class handing all form interactions based on this:

https://medium.com/@jeffochoa/vuejs-laravel-object-oriented-forms-f971cb50b7ab

Maybe it can be solved in a similar way? What is you preferred method of building an (edit) form with Vue/Apollo/GraphQL?


Solution

  • I can only tell you my preferred way. At it's most basic I do something like this...

    UserForm.vue

    <template>
    <form @submit.prevent="submitForm">
      <label>Name</label>
      <input type="text" v-model="proposedName" />
    
      <button type="submit">Submit</button>
      <button type="button" @click="cancel">Cancel</button>
    </form>
    </template>
    
    <script>
    import MyUserQuery from '/wherever/MyUserQuery.gql'
    import MyUserMutation from '/wherever/MyUserMutation.gql'
    
    export default {
      data() {
        return: {
          proposedName: ''
        }
      },
    
      methods: {
        submitForm() {
          this.$apollo.mutate({
            mutation: MyUserMutation,
            variables: {
              name: this.proposedName
            }
          })
    
          this.proposedName = ''
        }
      },
    
      apollo: {
        user: {
          query: MyUserQuery,
          result({data}) {
            this.proposedName = data.user.name
          }
        }
      }
    }
    </script>
    

    My proposedVariable thing is wordy, but I find it keeps me from confusing form data and Apollo data. I'm sure other people have other strategies.