GraphQL queries with multiple aliases and Apollo (Vue.js)

Viewed 1447

I'm trying to fetch data from a single collection type of my Strapi backend into a Vue.js project using Apollo. It works well with a single alias, but I'm having troubles making it work with multiple aliases.

I'm getting my data from a collection type of "campaigns" which has a boolean field of "archive". I want to create an array of "campaigns" that contains all of the campaigns that haven't been archived (archive = false) as well as an array of "archive" that contains all of the archived ones (archive = true).

This is my code:

import gql from "graphql-tag";

export default {
  name: "Campaigns",
  data() {
    return {
      campaigns: [],
      archive: []
    };
  },
  apollo: {
    campaigns: gql`
      query getCampaigns {
        campaigns: campaigns(where: { archive: "false" }, sort: "order:DESC") {
          name
          url
        }
        archive: campaigns(where: { archive: "true" }, sort: "order:DESC") {
          name
          url
        }
      }
    `
  }

The query returns an array of "campaigns", but the array of "archive" is still empty.

I've tried switching things up (put the archive alias first, switched the boolean values to make sure I can generally access the data of the archived campaigns etc.). The problem apparently lies with the "archive"-alias.

When I use the same query with Strapi's GraphQL playground I get the desired result:

{
  campaigns: campaigns(where: { archive: "false" }, sort: "order:DESC") {
    name
  }
  archive: campaigns(where: { archive: "true" }, sort: "order:DESC") {
    name
  }
}

... returns ...

{
  "data": {
    "campaigns": [
      {
        "name": "2020"
      },
      {
        "name": "2019"
      },
      {
        "name": "2018"
      },
      {
        "name": "2017"
      }
    ],
    "archive": [
      {
        "name": "2016"
      },
      {
        "name": "2015"
      }
    ]
  }
}

How can I make the query work in Vue.js with Apollo?

3 Answers

I think I've found a solution. Technically speaking I guess these are separate queries (which sort of defeats the purpose of aliases if I'm correct) but it does what I want:

  apollo: {
    campaigns: {
      query: gql`
        query {
          campaigns: campaigns(
            where: { archive: "false" }
            sort: "order:desc"
          ) {
            name
            url
          }
        }
      `
    },
    archive: {
      query: gql`
        query {
          archive: campaigns(where: { archive: "true" }, sort: "order:desc") {
            name
            url
          }
        }
      `
    }
  }

Apparently under some circumstance the initialization "apollo: { XYZ:" and the alias "query { XYZ:" have to match. I've seen in the docs that they don't necessarily have to match, but I don't fully understand when and why.

I guess I can't really tell what the initial parameter does.

You're using campaigns as the key for your entire query, so you need to initialize your data like this:

data() {
  return {
    campaigns: {
      campaigns: [],
      archive: [],
    },
  };
},

Then you can access each list through the key (i.e. campaigns.campaigns and campaigns.archive).

I believe the best way to do this is to use the update property: https://apollo.vuejs.org/guide/apollo/queries.html#name-matching

apollo: {
    campaigns: {
      query: gql`
        query {
          campaigns: campaigns(
            where: { archive: "false" }
            sort: "order:desc"
          ) {
            name
            url
          }
        }
      `
    },
    archive: {
      update: data => data.campaigns,
      query: gql`
        query {
          campaigns(where: { archive: "true" }, sort: "order:desc") {
            name
            url
          }
        }
      `
    }
  }
Related