11

I'm constructing a GraphQL query using vue-apollo and graphql-tag.

If I hardcode the ID I want, it works, but I'd like to pass the current route ID to Vue Apollo as a variable.

Does work (hardcoded ID):

  apollo: {
    Property: {
      query: PropertyQuery,
      loadingKey: 'loading',
      variables: {
        id: 'my-long-id-example'
      }
    }
  }

However, I'm unable to do this:

Doesn't work (trying to access this.$route for the ID):

  apollo: {
    Property: {
      query: PropertyQuery,
      loadingKey: 'loading',
      variables: {
        id: this.$route.params.id
      }
    }
  }

I get the error:

Uncaught TypeError: Cannot read property 'params' of undefined

Is there any way to do this?

EDIT: Full script block to make it easier to see what's going on:

<script>
import gql from 'graphql-tag'

const PropertyQuery = gql`
  query Property($id: ID!) {
    Property(id: $id) {
      id
      slug
      title
      description
      price
      area
      available
      image
      createdAt
      user {
        id
        firstName
        lastName
      }
    }
  }
`

export default {
  name: 'Property',
  data () {
    return {
      title: 'Property',
      property: {}
    }
  },
  apollo: {
    Property: {
      query: PropertyQuery,
      loadingKey: 'loading',
      variables: {
        id: this.$route.params.id // Error here!
      }
    }
  }
}
</script>
Michael Giovanni Pumo
  • 14,338
  • 18
  • 91
  • 140

3 Answers3

12

You can't have access to "this" object like that:

variables: {
  id: this.$route.params.id // Error here! 
}

But you can like this:

variables () {   
    return {
         id: this.$route.params.id // Works here!  
    }
}
Jonas
  • 691
  • 6
  • 4
9

Readimg the documentation( see Reactive parameters section) of vue-apollo you can use vue reactive properties by using this.propertyName. So just initialize the route params to a data property as then use it in you apollo object like this

export default {
  name: 'Property',
  data () {
    return {
      title: 'Property',
      property: {},
      routeParam: this.$route.params.id
    }
  },
  apollo: {
    Property: {
      query: PropertyQuery,
      loadingKey: 'loading',
         // Reactive parameters
      variables() {
        return{
            id: this.routeParam
        }
      }
    }
  }
} 
Vamsi Krishna
  • 30,568
  • 8
  • 70
  • 78
5

While the accepted answer is correct for the poster's example, it's more complex than necessary if you're using simple queries.

In this case, this is not the component instance, so you can't access this.$route

apollo: {
  Property: gql`{object(id: ${this.$route.params.id}){prop1, prop2}}`
}

However, you can simply replace it with a function, and it will work as you might expect.

apollo: {
  Property () {
    return gql`{object(id: ${this.$route.params.id}){prop1, prop2}}`
  }
}

No need for setting extra props.

brainbag
  • 1,007
  • 9
  • 23