Skip to main content

Use TakeShape with Vue

With its excellent Apollo plugin, Vue is a perfect frontend framework to use with TakeShape. Integrating our GraphQL API Mesh into your project couldn't be easier.

One important thing to remember is, Vue 2 and Vue 3 have some important differences that make the process of adding Apollo different for each version. We'll take you through both setup processes.

Getting your Project Information

Before you can begin integrating TakeShape into your Vue project, you'll need your API Endpoint and an API Key.

To connect to your TakeShape project, you need your API Endpoint and an API key.

If you haven't created a TakeShape project yet, follow this guide to do so.

If you already have a project, your API Endpoint will be in the TakeShape web client. In the home tab, look for the "Useful Snippets" section.

Copy the API Endpoint and save it somewhere secure.

To get an API Key, you'll have to create one. Read our docs on creating an API Key here.

Once you have both your API Key and TakeShape Endpoint, you'll add them to your project's .env file by appending their variable names with VUE_APP.

In our case, we'll name our variables like so:

.env
VUE_APP_TAKESHAPE_ENDPOINT=https://api.takeshape.io/project/6cdbcc52-5697-475b-872e-fcb6fd0e00d0/v3/graphql

VUE_APP_TAKESHAPE_API_KEY=7b9171f34e104aeba972941bcfb7767d
danger

API keys used in frontend applications are exposed to the browser, even if you use environment variables. When you create an API Key, always use the fewest permissions necessary for your application. Learn more in our permissions guide.

Creating a Vue Project

To create a vue project, first install the Vue CLI. Open your console anywhere and enter the following command:

npm install -g @vue/cli

Now you just need to use the vue create command. Navigate to the folder where you keep your projects, and enter the below into the terminal.

vue create project-name-here

You will be asked if you want to create a Vue 2 or Vue 3 project. Vue 3 is of course newer, but not as well-supported by most Vue plugins. To learn how to integrate TakeShape with Vue 2, continue to the next section. To learn how to use TakeShape with Vue 3, check out our section on Vue 3 below.

Using TakeShape with Vue 2

Configuring Apollo with Vue requires extensive modification your project's main.js file. Before we can begin setting up this file, we need to run the vue add command to add Apollo to our project.

vue add apollo

If you're warned to commit your changes to git before proceeding, you should enter N and handle the issue appropriately. If you aren't interested in committing this project yet, enter Y. For the rest of the questions, enter N.

Next, we'll install a few dependencies.

npm install apollo-cache-inmemory apollo-client apollo-link-http

Now open up your project's main.js file and add the following imports to the top:

main.js
import ApolloClient from "apollo-client";
import { HttpLink } from "apollo-link-http";
import { InMemoryCache } from "apollo-cache-inmemory";
import VueApollo from "vue-apollo";

To tell Vue to use Apollo, you'll want to call the Vue.use() method immediately after all your import statements.

main.js
import ApolloClient from "apollo-client";
import { HttpLink } from "apollo-link-http";
import { InMemoryCache } from "apollo-cache-inmemory";
import VueApollo from "vue-apollo";

Vue.use(VueApollo);

Next we'll create an Apollo client, which we'll configure with our endpoint and API Key to connect to our TakeShape project. First, we have to create an HttpLink with our Endpoint URL and API Key. Study the code below:

main.js
const link = new HttpLink({
uri: process.env.VUE_APP_TAKESHAPE_ENDPOINT,
fetch,
headers: getHeaders()
});

In the above code, you'll notice that we're calling a method named getHeaders(). To authenticate your GraphQL query, you must put your API Key into the header of the fetch request.

To pass headers to your HttpLink, you must create a method that returns an object which contains your headers. Ours will be simple, as TakeShape uses Bearer Token authentication for its GraphQL API. Add a getHeaders() method like the one below into your code, prior to your new HttpLink() constructor.

main.js
const getHeaders = () => {
const headers = {
Authorization: `Bearer ${process.env.VUE_APP_TAKESHAPE_API_KEY}`
};
return headers;
};

const link = new HttpLink({
uri: process.env.VUE_APP_TAKESHAPE_ENDPOINT,
fetch,
headers: getHeaders()
});

Finally, we're ready to create our Apollo client using the HttpLink we've constructed.

main.js
const client = new ApolloClient({
link: link,
cache: new InMemoryCache()
});

After that, we need to create an Apollo provider, which will pass our Apollo Client instance to our app. This will allow us to make queries and mutations on our TakeShape project. The below code is all we need:

main.js
const apolloProvider = new VueApollo({
defaultClient: client,
})

Now we're ready to add our provider to our app. In the below method, App is the component imported from our main App file.

main.js
new Vue({
apolloProvider,
render: h => h(App)
}).$mount("#app");

With this configured, we're ready to make GraphQL queries in our Vue components. For more information, check out the Vue Apollo Official Documentation.

The final code should look like this:

main.js
import Vue from 'vue'
import App from './App.vue'
import ApolloClient from "apollo-client";
import { HttpLink } from "apollo-link-http";
import { InMemoryCache } from "apollo-cache-inmemory";
import VueApollo from "vue-apollo";

Vue.use(VueApollo);

const getHeaders = () => {
const headers = {
Authorization : `Bearer ${process.env.VUE_APP_TAKESHAPE_API_KEY}`
};
return headers;
};

const link = new HttpLink({
uri: process.env.VUE_APP_TAKESHAPE_ENDPOINT,
fetch,
headers: getHeaders()
});

const client = new ApolloClient({
link: link,
cache: new InMemoryCache()
});

const apolloProvider = new VueApollo({
defaultClient: client,
})

new Vue({
apolloProvider,
render: h => h(App)
}).$mount("#app");

Adding TakeShape to your Vue 2 components

For this example, we'll be adding a list of product collections from an ecommerce backend to our Vue project.

In Vue 2, rendering components based on data returned from a GraphQL query is easy. First, navigate to the component you want to add the data to. Our example will be the HelloWorld.vue file that is auto-generated by the vue create cli command.

In the script tag, import 'graphql-tag' to enable making a query.

HelloWorld.vue
<script>
import gql from 'graphql-tag'
</script>

Now in your default export, add a property called apollo that contains your query. Our query will be getCollectionList, but you can use any query defined in your TakeShape schema. Read our docs to learn more about adding queries to your schema.

You'll then add the gql method, along with your query. See the code below:

HelloWorld.vue
<script>
import gql from 'graphql-tag'

export default {
name: 'HelloWorld',
props: {
msg: String
},
apollo: {
getCollectionList: gql`
query {
getCollectionList {
items {
_id
title
products {
_id
name
}
}
}
}
`,
}
}
</script>

With the above query, we're retrieving an array of items which represent our ecommerce product collections list. We want the id, title, and array of products contained within each collection. For the products, we want the id and title.

This query will run when our component renders, and when the query is complete our template will be generated. But let's lay out the structure of our template below. We want to list each collection name, and the names of the products within them.

HelloWorld.vue
<template>
<div>
<h1>Product Collections</h1>
<div v-for="item in getCollectionList.items" :key="item._id">
<h2>{{item.title}}</h2>
<ul>
<li v-for="product in item.products" :key="product._id">
{{product.name}}
</li>
</ul>
</div>
</div>
</template>

The above template will cycle through every collection in the list and construct a div containing information for each.

The final .vue file should look like this:

HelloWorld.vue
<template>
<div>
<h1>Product Collections</h1>
<div v-for="item in getCollectionList.items" :key="item._id">
<h2>{{item.title}}</h2>
<ul>
<li v-for="product in item.products" :key="product._id">
{{product.name}}
</li>
</ul>
</div>
</div>
</template>

<script>
import gql from 'graphql-tag'

export default {
name: 'HelloWorld',
props: {
msg: String
},
apollo: {
getCollectionList: gql`
query {
getCollectionList {
items {
_id
title
products {
_id
name
}
}
}
}
`,
}
}
</script>

This is what your page should look like:

And you're finally done. To run your project, enter npm run serve into the console.

For more information on creating Vue 2 projects with GraphQL, check out these excellent docs by Hasura on the subject.

Using TakeShape with Vue 3

As is the case with Vue 2, Configuring Apollo with Vue 3 requires you to modify your project's main.js file. Before we can begin setting up this file, we need to install a few dependencies.

npm install @apollo/client @vue/apollo-composable

Now we'll jump into the main.js file. Below is the code for all the imports you'll need to make.

main.js
import { ApolloClient, HttpLink, InMemoryCache } from '@apollo/client/core'
import { createApp, provide, h } from 'vue'
import { DefaultApolloClient } from '@vue/apollo-composable'
import App from './App.vue'

First we'll need to create an Apollo Client object, which stores all the information about the connection we want to make to TakeShape's GraphQL API. Step one is to create an HttpLink with our Endpoint URL and API Key. Study the code below:

main.js
const link = new HttpLink({
uri: process.env.VUE_APP_TAKESHAPE_ENDPOINT,
fetch,
headers: getHeaders()
});

Before the above code can work, we must define the getHeaders() method. To pass headers to your HttpLink, you must create a method that returns an object which contains your headers. Since we're just adding Authorization and a Bearer Token, ours will be simple. Add a getHeaders() method like the one below into your code, above your new HttpLink() constructor.

main.js
const getHeaders = () => {
const headers = {
Authorization : `Bearer ${process.env.VUE_APP_TAKESHAPE_API_KEY}`
};
return headers;
};

const link = new HttpLink({
uri: process.env.VUE_APP_TAKESHAPE_ENDPOINT,
fetch,
headers: getHeaders()
});

Finally, we're ready to create our Apollo client using the HttpLink we've constructed.

main.js
const apolloClient = new ApolloClient({
link: link,
cache: new InMemoryCache()
});

To pass our Apollo Client instance to our app, we need to use Vue 3's new createApp() method. We'll also use the DefaultApolloClient, which Apollo provides for use-cases where you don't need to customize too many details of how Apollo works in your app. Learn more by checking out the docs.

Below is how it should be configured:

main.js
createApp({
setup () {
provide(DefaultApolloClient, apolloClient)
},
render: () => h(App),
}).mount('#app')

Now we're ready to make GraphQL queries in our Vue components. To learn more about integrating Apollo into Vue 3, check out the official docs on the subject.

The final main.js file should look like this:

main.js
import { ApolloClient, HttpLink, InMemoryCache } from '@apollo/client/core'
import { createApp, provide, h } from 'vue'
import { DefaultApolloClient } from '@vue/apollo-composable'
import App from './App.vue'

const getHeaders = () => {
const headers = {
Authorization : `Bearer ${process.env.VUE_APP_TAKESHAPE_API_KEY}`
};
return headers;
};

const link = new HttpLink({
uri: process.env.VUE_APP_TAKESHAPE_ENDPOINT,
fetch,
headers: getHeaders()
});

const apolloClient = new ApolloClient({
link,
cache: new InMemoryCache(),
})

createApp({
setup () {
provide(DefaultApolloClient, apolloClient)
},
render: () => h(App),
}).mount('#app')

Adding TakeShape to your Vue 3 components

The preferred method for rendering data pulled from GraphQL queries in Vue 3 is with the Vue Apollo Composition API.

The major difference between this method and Vue 2's simple use of the graphql-tag is that you'll be using Apollo's useQuery hook to make your GraphQL query. What's returned will be a Vue ref that you can pull into your template code. Learn more about useQuery here.

For our purposes, we'll create a template inside the HelloWorld.vue component that renders items based on the data we pull from our TakeShape API Mesh.

Our query will be getCollectionList, but you can use any query defined in your TakeShape schema. Read our docs to learn more about adding queries to your schema.

In the <script> tag of your Vue component, add the following imports to the top:

HelloWorld.vue
<script>
import { useQuery, useResult} from '@vue/apollo-composable'
import { gql } from '@apollo/client/core'
</script>

Now we need to add a setup() method to our export object. When you use setup() in the object your component exports in Vue, it runs the code prior to rendering the content in the template. Learn more from the official Vue 3 docs.

Add the setup() method as shown in the example below:

HelloWorld.vue
export default {
name: 'HelloWorld',
props: {
msg: String
},
setup(){}

Okay, so now we need to use useQuery from the Vue Apollo Composition API. You'll call useQuery and pass the query you want to run as a parameter, with the gql tag appended to the front. Study the code below:

HelloWorld.vue
export default {
name: 'HelloWorld',
props: {
msg: String
},
setup(){
const {result} = useQuery(gql`
query {
getCollectionList {
items {
_id
title
products {
_id
name
}
}
}
}
`)
}
}

You'll notice we're destructuring a result object from the result of the useQuery hook.

But we can't use the result in our code yet. We first need to call useResult, passing our result, a default value, and a method as the arguments. The result is what we want to make into a usable Vue ref, so we can reference it in our template. The default value is what will be returned if useResult fails. The method is how we customize what we get back from useResult. Check it out below:

HelloWorld.vue
    const getCollectionList = useResult(result, null,
data=>data.getCollectionList
)
return { getCollectionList }

As you can see above, the ref we'll use in our template will ultimately be called getCollectionList. We get that data because the method we passed to useResult returned it. Learn more by reading the official docs on useResult.

With the above query, we're retrieving an array of items which represent our ecommerce product collections list. We want the id, title, and array of products contained within each collection. For the products, we want the id and title.

To display this content, we'll use v-for to loop through the elements of the items and products arrays.

HelloWorld.vue
<template>
<div>
<h1>Product Collections</h1>
<div v-for="item in getCollectionList.items" :key="item._id">
<h2>{{item.title}}</h2>
<ul>
<li v-for="product in item.products" :key="product._id">
{{product.name}}
</li>
</ul>
</div>
</div>
</template>

You'll notice in the above code that we're conditionally rendering different divs based on the result of our GraphQL query. In the div that's rendered when our data successfully loads, we're creating an <h2> that displays the title of the item, which in this case is a product collection. Then we have an unordered list which is populated with <li> elements for every product in the collection. Inside each <li> is the product's name.

Your final HelloWorld.vue should look like this:

HelloWorld.vue
<template>
<div>
<h1>Product Collections</h1>
<div v-for="item in getCollectionList.items" :key="item._id">
<h2>{{item.title}}</h2>
<ul>
<li v-for="product in item.products" :key="product._id">
{{product.name}}
</li>
</ul>
</div>
</div>
</template>

<script>
import { useQuery, useResult} from '@vue/apollo-composable'
import { gql } from '@apollo/client/core'

export default {
name: 'HelloWorld',
props: {
msg: String
},
setup(){
const {result} = useQuery(gql`
query {
getCollectionList {
items {
_id
title
products {
_id
name
}
}
}
}
`)

const getCollectionList = useResult(result, null,
data=>data.getCollectionList
)

return { getCollectionList }
}
}
</script>

The page should look like this:

Now you're all set. Just run your project with npm run serve, and you'll see your dynamically-generated content, pulled straight from your TakeShape project's API Mesh.

Still need help? Get in touch with us.