Introduction
REST API design pattern is one of the best practices when building API’s for the back end of any application. It’s benefits supersede it’s downside. When fetching data from an extensive REST application with many database relationships, there is can be an information overload problem.
This post will explore
- How GraphQL helps solve this problem and how implementing GraphQL in Strapi is even easier than we think.
- How to use of Apollo in Vue.js applications to make GraphQL queries to a Strap backend server
- Making CRUD requests using both the Strapi GraphQL playground and Apollo GraphQL in a Vue.js app
- Obtaining a JSON web tokens (JWT) for users in case of authenticated requests
GraphQL Overview
Cons Of The REST API
In a typical REST API-based application, data is fetched from the back end and displayed on the front end. There is the problem of overloading information (mentioned earlier). I'll further explain this using an example.
A front end developer wants to fetch just the userName
of a user in the database. He expects his response to look like this
user :{
userName:"alloyking12300"
}
but instead he gets this:
user: {
userName:"alloying12300",
email:"testemail@email.com",
age: 21,
profile: {
img:"image/path",
profession:"developer"
}
}
Now you see, the response above is packed with lot of data that we do not need. It is, of course, possible to display what you need on the front end and be done with it, but this has a massive impact on the performance of the application. In the quest to solve this, GraphQL was born.
Secondly, REST API applications have too many routes. In very complex applications, the routes can become challenging to handle and manage. GraphQL helps us tackle this too.
GraphQL
GraphQL is a query language for your API and a server-side runtime for executing queries using a type system you define for your data.
GraphQL provides developers access to just the particular data they need in a specific request by using just one endpoint (l like to think of it as a smart endpoint), which understands what the front end application expects and returns precisely.
The bulk of the technicalities of implementing GraphQL have been simplified when using Strapi.
Strapi GraphQL
Strapi is an easily customizable open-source headless CMS. Strapi’s API can return responses in both REST or GraphQL. In this tutorial, we will look at how GraphQL works in Strapi.
Implementing GraphQL in Strapi
To explore the wonders of GraphQL in Strapi, we need a Strapi project to test. Let's proceed by creating a new Strapi project using the following command:
yarn create strapi-app my-project --quickstart
or
npx create-strapi-app my-project --quickstart
This command will create a new Strapi project and launch it in your browser like this:
When you fill in this form, you will create your first Admin User. After that, the application will redirect to the dashboard.
Blog Collection Type
We need content to test our GraphQL API. Let's create a blog collection type and add some blog posts to it.
On the left navigation menu, from the plugin section, click on Content-TypesBuilder. Fill the form to create a new Collection Type.
We need to modify our Blog content type further to contain the Title, Body, and Date fields. These are necessary fields that we need. Fill the form and select these fields. You can use the images below for guidance.
Repeat the process in the image above for the rest of the fields. Then save. After saving, we should have a newly created Collection Type of Blog.
Add Blog Posts
We have created our Collection Type. We need few blog posts to be able to explore how GraphQL works in Strapi.
From the Collection Type section in the navigation menu, click on Blogs→Add new blog post.
Lets create a blog post with some dummy text as this is for educational purpose only
To use GraphQL in Strapi, we need to install the GraphQL Plugin using the command below
yarn strapi install graphql
On completion of the installation, our Strapi application is set for GraphQL. Strapi also has a Playground for testing GraphQL operations. We can access this Playground using http://localhost:1337/graphql.
The GraphQL Playground has an inbuilt text editor for you to enter your GraphQL commands, a play button for you to run your code and a screen to display the return values, error or success message.
Before we proceed to the Strapi playground to test, we need to grant the public user access to the Blogs collection type. Authentication will be covered later on in this post. For now, lets get started with the public user. To do this, click on settings→roles→permissions to grant all the necessary access to the Blogs and save.
Strapi GraphQL Playground
The Strapi GraphQl playground is a development environment for you to interact with your Strapi application using GraphQl. Lets proceed by carrying out CRUD operations on our blog content using the playground.
In order to interact with the GraphQL server, we either need to write a Query or a Mutation.
A GraphQL query is used to read or fetch data from the server while a mutation is used to write or post values. For easier understanding you can think of it as GET request and POST request where Query is used to make GET request and Mutation to make POST request.
Fetching Multiple Contents
With that said, lets getting started by reading from our GraphQL server. We need to write a query for this. The code below is a basic GraphQL query to fetch all Blogs from our Strapi backend. It returns the Id
, Title
and Body
.
query{
blogs{
id
Title
Body
}
}
Enter the code in your Strapi playground and it should fetch all Blog posts in your Blog collection
Fetching Single Content:
We can fetch a single blog post from the collection by passing along a unique key. In our case, we will pass along the id
.
query {
blog(id:"3"){
id
Title
Body
}
}
Create Content
Remember when we talked about Queries and Mutations earlier, we will use a Mutation to create a new entry. Lets create a new blog post to continue.
mutation {
createBlog(input: { data: { Title: "Fifth Post", Body: " This is the fifth blog post. It was created using a graphQl mutaiton from the strapi graphql playground" } }) {
blog {
Title
Body
}
}
}
The function createBlog
accepts input
object which in turn accepts a data
object with inputs to insert. This function derives its name from the name of the Strapi collection type. If we wanted to create a new user for instance, it would be createUser
instead. The Title
and Body
are corresponding fields in the Blog
collection. In the case of a different collection type, they should correspond with the fields of the collection type.
Update Content
We use Mutations for update features too. Lets edit the post we just created like so:
mutation {
updateBlog(
input: {
where: { id: "5" }
data: { Title: "Fifth Post Edited", Body: "This is the fifth blog post (edited). This was created using a graphQl mutaiton from the strapi graphql playground" }
}
) {
blog {
Title
Body
}
}
}
updateBlog
method accepts an input
object that specifies the id
of the post we intend to edit and the data in the where
and data
objects respectively.
Delete Content
let us delete this post to see if it actually goes away. The Mutation below will do just that.
mutation {
deleteBlog(input: { where: { id: "5" } }) {
blog {
Title
Body
}
}
}
deleteBlog
method accepts an input
object with a where
object that accepts the id
of the post to delete. After a successful delete, the blog returns null
Authentication
In order for a user to access any protect route in Strapi, the user needs to be authenticated. We can implement authentication in our Strapi application using GraphQl too. Lets get started by creating a new user
mutation {
register(input: { username: "alloyuser", email: "email@gmail.com", password: "password" }) {
jwt
user {
username
email
}
}
}
we used a new function here. The register
function which accepts an intput
object that contains the user details to be created.
After successfully creating a user, it returns the user
object and a jwt
token. We need the token to be passed along as Authorization
header in the form of "Authorization": "Bearer YOUR_JWT_GOES_HERE"
. In the Strapi GraphQL playground, this can be set in the HTTP header section. That way it will be passed along with every request and user will be able to access protected routes.
In the case of an already existing user, Users can login to generate a token. Lets login using the details of the user we just created above.
mutation {
login(input: { identifier: "seconduser@gmail.com", password: "password" }) {
jwt
}
}
this would also return a jwt
token for access like so
Filters
To make more complex GraphQL queries, we can apply some filters to the query. Lets explore some of the most useful filters.
-
limit
type => integer : Places a limit on the number of returned data. -
start
type => integer: Ability to specify where the query will start. -
sort
type => string: Sorts data to be returned -
publicationState
type => PublicationState: Only select entries matching the publication state provided. -
locale
type => string: This requires the (i18n) plugin plugin to be activated and properly configured. It can be used to fetch contents from a selected locale - Handled states are:
-
live
: Return only published entries (default) -
preview
: Return both draft entries & published entries
-
-
<field>:asc
or<field>:desc
-
where
(object): Define the filters to apply in the query.-
<field>
: Equals. -
<field>_ne
: Not equals. -
<field>_lt
: Lower than. -
<field>_lte
: Lower than or equal to. -
<field>_gt
: Greater than. -
<field>_gte
: Greater than or equal to. -
<field>_contains
: Contains. -
<field>_containss
: Contains sensitive. -
<field>_ncontains
: Doesn't contain. -
<field>_ncontainss
: Doesn't contain, case sensitive -
<field>_in
: Matches any value in the array of values. -
<field>_nin
: Doesn't match any value in the array of values. -
<field>_null
: Equals null/Not equals null
-
To better understand how filters can be used, lets make a query to fetch all the Blog post with id
greater than 2
query {
blogs(where: { id_gt: "2" }) {
Title
Body
}
}
Here we used the where
object and <field>_gt
. id
in our case is the field
. We added the gt
(greater than) prefix to get all post with id
greater than 2
We can extend it further by adding a limit
to the query and also sorting the result in descending order like so
query {
blogs(limit: 2, sort: "id:desc" where: { id_gt: "1" }) {
Title
Body
}
}
The result is a listed of sorted posts in descending order starting from the second post with an id
of 2 downwards
Explore Strapi GraphQL with Vue.js
Let's go a little further by interacting with Strapi GraphQL from an external Vue.js application. To get started, we need to create a Vue.js application. You can create it using the following Vue CLI command:
vue create strapiproject
Make sure you have the Vue CLI installed globally. If you need help installing the CLI or upgrading to the latest version of Vue.js, follow this tutorial here for details.
After a successful installation, launch the project using the following command:
npm run serve
Now you should be able to serve up the Vue.js application on the browser. Find a screenshot of my served screen below:
Install Apollo
To interact with GraphQL from our Vue.js application, we need to install Apollo and query our Strapi GraphQL server using Apollo.
Install Apollo using the following command:
vue add apollo
Apollo boost and Apollo client are the two variations of Apollo that can be installed in a Vue.js application. We will proceed with the Apollo client as this best suits the purpose of this tutorial. Check Apollo official documentation for more details.
Install Apollo client using the following command:
npm install --save vue-apollo graphql apollo-client apollo-link apollo-link-http apollo-cache-inmemory graphql-tag
Or:
yarn add vue-apollo graphql apollo-client apollo-link apollo-link-http apollo-cache-inmemory graphql-tag
In the HTML section, I used Bootstrap classes for basic styling. There are many different ways you can add bootstrap to your Vue.js project, but for this tutorial, I used a CDN (Content delivery network).
Open public→index.html, add the following to the head section of the page:
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
add this before the closing Body tag of the page
<!-- built files will be auto injected -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-Piv4xVNRyMGpqkS2by6br4gNJ7DXjqk09RmUpJ8jgGtD7zP9yug3goQfGII0yAns" crossorigin="anonymous"></script>
After the installation, next, we need to configure Apollo to work in our application. Edit src→main.js file and add the following code
import Vue from 'vue'
import App from './App.vue'
// import { createProvider } from './vue-apollo'
Vue.config.productionTip = false
// custom
import VueApollo from 'vue-apollo'
Vue.use(VueApollo)
import { ApolloClient } from 'apollo-client'
import { createHttpLink } from 'apollo-link-http'
import { InMemoryCache } from 'apollo-cache-inmemory'
// HTTP connection to the API
const httpLink = createHttpLink({
// You should use an absolute URL here
uri: 'http://localhost:1337/graphql',
})
// Cache implementation
const cache = new InMemoryCache()
// Create the apollo client
const apolloClient = new ApolloClient({
link: httpLink,
cache,
})
const apolloProvider = new VueApollo({
defaultClient: apolloClient,
})
new Vue({
// apolloProvider: createProvider(),
apolloProvider,
render: h => h(App)
}).$mount('#app')
In the code above, URI: 'http://localhost:1337/graphql
'
, points to the Strapi GraphQL endpoint. I have my Strapi server running in that port. Do not close your Strapi project while working on Vue.js.
Vue Router
Now we have GraphQL configured and working in our app. Lets try fetching post from our GraphQL backend. This will require a router feature. Lets install Vue router using NPM to continue.
npm install vue-router
OR
yarn add vue-router
Once its done installing, we need to configure the router to work with our application effectively. Head over to src→main.js and add the following block of code
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const router = new VueRouter({
mode: 'history',
routes : [
{ path: '/', component: require('./components/HelloWorld.vue').default },
],
})
Then add this router
to your vue instance like so
new Vue({
apolloProvider,
router: router, //add this
render: h => h(App)
}).$mount('#app')
We created just one route for our home page. Lets edit our App.vue component to work with our router. Add the following
<template>
<div id="app">
<Nav />
<router-view></router-view>
</div>
</template>
<script>
import Nav from "./components/Nav.vue";
export default {
name: "App",
components: {
Nav,
},
};
</script>
Notice the Nav.vue component. I added it for ease of navigation. The component was created in the /components directory.
Add the following to your Nav component to create a basic bootstrap navigation
<template>
<div>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<router-link class="navbar-brand" to="/">Home</router-link>
<button
class="navbar-toggler"
type="button"
data-toggle="collapse"
data-target="#navbarNav"
aria-controls="navbarNav"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<router-link class="nav-link" to="#">Link</router-link>
</li>
<li class="nav-item">
<router-link class="nav-link" to="#">Link</router-link>
</li>
</ul>
</div>
</nav>
</div>
</template>
Fetching Post
Lets make our actual GraphQL query from the Vue.js application to access data from the Strapi GraphQL server.
Our Vue app has just one component at the moment named HelloWorld, I renamed mine to Home Click on src→components→Home.vue and replace the content of the page with the following:
<template>
<div>
<div class="container">
<div class="container">
<div class="customPadding">
<div class="row">
<div class="col-sm">
<div class="customCard">
<h1
style="
font-size: 3rem;
text-align: center;
padding-bottom: 6rem;
"
>
Blog Post
</h1>
</div>
<div v-for="blog in blogs" :key="blog.id">
<router-link
class="nav-link"
:to="{ path: '/blog/' + blog.id }"
>
<div class="container">
<div class="customCard">
<div
class="
card
shadow-lg
p-3
mb-5
bg-white
rounded
mr-5
ml-5
"
>
<div class="card-head" style="padding: 4rem">
<h1 style="font-size: 6rem">
{{ blog.Title }}
<hr />
</h1>
</div>
<div class="card-body text-center">
<p style="line-height: 26pt">{{ blog.Body }}</p>
</div>
</div>
</div>
</div>
</router-link>
<br />
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import gql from "graphql-tag";
export default {
name: "HelloWorld",
data() {
return {
blogs: [],
};
},
apollo: {
blogs: {
query: gql`
query {
blogs {
id
Title
Body
}
}
`,
},
},
};
</script>
<style>
.customPadding {
margin-top: 12rem !important;
margin-bottom: 12rem !important;
/* padding: 4rem; */
}
</style>
First, we imported gql
, used in making our GraphQL query. We stored the response data from the query in blogs:[]
array.
Next, the data in this array was looped through and displayed in the HTML section of this component. We added a router link to fetch each post to the displayed post in the loop. This router link accepts the post id
. The id
is passed along to the single post component.
Lets register this newly created URL as a route. To do this, open main.js once again and update the router
with the newly created route like so
const router = new VueRouter({
mode: 'history',
routes : [
{ path: '/', component: require('./components/Home.vue').default },
{ path: '/blog/:id', component: require('./components/SingleBlog.vue').default},
],
})
We also need to create a new component named SingleBlog.vue The router link already points to it. Create this in the Components folder like so
Now, your Vue app should be able to fetch data from the Strapi GraphQL server like my page below.
Fetching Single Post
We already added a router link to each displayed blog post to fetch single post, add the following to our SingleBlog.vue component
<template>
<div>
<div class="container customPadding">
<div class="customPadding">
<div class="card card shadow-lg p-3 mb-5 bg-white rounded mr-5 ml-5">
<div class="container">
<div class="card-head" style="padding: 4rem">
<h1 style="font-size: 6rem">{{ blog.Title }}</h1>
</div>
<hr />
<p style="line-height: 26pt">
{{ blog.Body }}
</p>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import gql from "graphql-tag";
export default {
name: "SingleBlog",
data() {
return {
blog: [],
id: this.$route.params.id,
};
},
apollo: {
blog: {
query: gql`
query blog($id: ID!) {
blog(id: $id) {
id
Title
Body
}
}
`,
variables() {
return {
id: this.id,
};
},
},
},
};
</script>
<style>
.customPadding {
margin-top: 12rem !important;
margin-bottom: 12rem !important;
/* padding: 4rem; */
}
</style>
Here, we modified our GraphQL query to fetch single post by passing the post id
along with the query. If your observant, you will notice that the QraphQL query is a little different from the query in the playground. This is because in Vue we cannot access the value of this.$route.params.id
from within the query. We have to pass it along as a variable using
variables() {
return {
id: this.id,
};
For more on GraphQL queries with Vue click here. If everything is done right, you should be able to click on a post from the home page and be redirected to a single page that will display the content of the post.
Delete Post
Lets take it even further by implementing the delete feature. Lets add a button for the delete functionality. Edit the code in SingleBlog.vue and the following in the card-head
section of your html
<div class="card-head" style="padding: 4rem">
<h1 style="font-size: 6rem">{{ blog.Title }}</h1>
<button type="button" class="btn btn-primary mr-2">Edit</button>
<button
type="button"
class="btn btn-danger"
@click="deletePost()"
>
Delete
</button>
</div>
Notice that we already add @click="deletePost()
to the Delete Button, that method is not yet created. In the JavaScript section of your component, add the following after the data function.
methods: {
deletePost() {
const check = confirm();
if (check) {
this.$apollo
.mutate({
mutation: gql`
mutation deleteBlog($id: ID!) {
deleteBlog(input: { where: { id: $id } }) {
blog {
Title
Body
}
}
}
`,
variables: {
id: this.id,
},
})
} else {
return false;
}
},
},
On click of the button, its call the deletePost()
function. We used a JavaScript confirm function to confirm before making the GraphQL query to delete the post. Notice that variables
in the GraphQl mutation is an object not a function like we have in the query earlier.
Edit Post
Lets take a look at how we can implement updating of our post content from within our Vue.js application. We need a form for this so I added a bootstrap Modal with a form to the SingleBlog.vue component using the following
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Edit Post</h5>
<button
type="button"
class="close"
data-dismiss="modal"
aria-label="Close"
>
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form>
<div class="form-group">
<label for="recipient-name" class="col-form-label"
>Title:</label
>
<input type="text" v-model="blog.Title" class="form-control" />
</div>
<div class="form-group">
<label for="message-text" class="col-form-label">Body:</label>
<textarea class="form-control" v-model="blog.Body"></textarea>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" @click="editPost()">
Save
</button>
</div>
</div>
</div>
</div>
The Edit button was also changed to contain code to open the modal like this
<button type="button" class="btn btn-primary mr-2" data-toggle="modal" data-target="#exampleModal" data-whatever="@mdo"> Edit</button>
We used v-model="blog.Title"
and v-model="blog.Body"
to bind the post Title and Body to the respective form fields. @click="editPo
s
t()
"
was called upon submission of the form. Lets add that function to the Methods object of our app like this.
editPost() {
this.$apollo
.mutate({
mutation: gql`
mutation updateBlog($id: ID!, $Title: String!, $Body: String!) {
updateBlog(
input: {
where: { id: $id }
data: { Title: $Title, Body: $Body }
}
) {
blog {
Title
Body
}
}
}
`,
variables: {
id: this.id,
Title: this.blog.Title,
Body: this.blog.Body,
},
})
.then((res) => {
console.log(res);
alert("Edited");
});
},
The method looks a lot similar to that of the Delete function implemented above except for the data we passed along in this case and the additional two variable added $Title: String!
and $Body: String!
. But now you should be able to open and close the Edit form modal
You should also be able to Edit post and save like so
Create A Post
Thus far, we have covered Reading, Editing and Deleting post from our GraphQL server. Lets look at how we can create new post in this section. We need a new router and a new component for this feature. In your Main.js add a new route to the already existing
const router = new VueRouter({
mode: 'history',
routes : [
{ path: '/', component: require('./components/Home.vue').default },
//add this
{ path: '/create', component: require('./components/CreatePost.vue').default },
{ path: '/blog/:id', component: require('./components/SingleBlog.vue').default},
],
})
further more, we need to create the component that our newly created route points to. In src→components create a new component name CreatePost.vue like we have in the route.
Edit the content of the component and add the following code to it to display our form, validate and create a new post
<template>
<div class="container">
<div class="mt-5">
<div class="card-head" style="padding: 4rem">
<h1 style="font-size: 6rem">
Create New Post
<hr />
</h1>
</div>
<div class="card card shadow-lg p-3 mb-5 bg-white rounded mr-5 ml-5">
<form>
<div class="form-group">
<label for="recipient-name" class="col-form-label">Title:</label>
<input type="text" v-model="Title" class="form-control" />
</div>
<div class="form-group">
<label for="message-text" class="col-form-label">Body:</label>
<textarea class="form-control" rows="8" v-model="Body"></textarea>
</div>
</form>
<div>
<button type="button" class="btn btn-primary" @click="createPost()">
Save
</button>
</div>
</div>
</div>
</div>
</template>
<script>
import gql from "graphql-tag";
export default {
data() {
return {
Title: "",
Body: "",
};
},
methods: {
createPost() {
if (this.Title && this.Body) {
this.$apollo
.mutate({
mutation: gql`
mutation createBlog($Title: String!, $Body: String!) {
createBlog(input: { data: { Title: $Title, Body: $Body } }) {
blog {
Title
Body
}
}
}
`,
variables: {
Title: this.Title,
Body: this.Body,
},
})
.then((res) => {
console.log(res);
alert("Post Created");
});
} else {
alert("all fields are required");
}
},
},
};
</script>
We used basic bootstrap to beautify our HTML form. Vue.js v-model
was used to binned form values to its respective elements. in createPost()
method, we validated this form and created our GraphQL query to create a new post.
Lets edit the Navbar and add a link to this component.
<template>
<div>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<router-link class="navbar-brand" to="/">Home</router-link>
<button
class="navbar-toggler"
type="button"
data-toggle="collapse"
data-target="#navbarNav"
aria-controls="navbarNav"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<router-link class="nav-link" to="/create"
>Add New Post</router-link
> //createPost Link added here
</li>
<li class="nav-item">
<router-link class="nav-link" to="#">Link</router-link>
</li>
</ul>
</div>
</nav>
</div>
</template>
lets go ahead and create a new post to see our form in action
After creating the new post, you can find it in the home page like so
Signup
We have been able to explore the CRUD feature of GraphQL using Vue.js. Let us scratch the surface of implementing authentication by creating a new user using GraphQL. A newly created user returns a jwt
. When making request to protected routes in GraphQL, you need to pass the jwt
token along with the request.
With that said, lets proceed. We need to create a new route and a new component for this and also edit the navigation bar once more.
in src→components create a component name Authentication.vue. in the main.js, add a new route pointing to this component like so
const router = new VueRouter({
mode: 'history',
routes : [
{ path: '/', component: require('./components/Home.vue').default },
{ path: '/create', component: require('./components/CreatePost.vue').default },
{ path: '/blog/:id', component: require('./components/SingleBlog.vue').default},
//newly created route
{ path: '/user/signup', component: require('./components/Authentication.vue').default},
],
})
edit the last link in the nav menu and add a link to the route
<template>
<div>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<router-link class="navbar-brand" to="/">Home</router-link>
<button
class="navbar-toggler"
type="button"
data-toggle="collapse"
data-target="#navbarNav"
aria-controls="navbarNav"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<router-link class="nav-link" to="/create"
>Add New Post</router-link
>
</li>
<li class="nav-item">
<router-link class="nav-link" to="/user/signup"
>sign up</router-link
>
</li>
</ul>
</div>
</nav>
</div>
</template>
In the newly created component, add the following
<template>
<div class="container">
<div class="mt-5">
<div class="card-head" style="padding: 4rem">
<h1 style="font-size: 6rem">
Create New User
<hr />
</h1>
</div>
<div class="card card shadow-lg p-3 mb-5 bg-white rounded mr-5 ml-5">
<form>
<div class="form-group">
<label for="recipient-name" class="col-form-label"
>User Name:</label
>
<input type="text" v-model="username" class="form-control" />
</div>
<div class="form-group">
<label for="recipient-name" class="col-form-label">Email:</label>
<input type="email" v-model="email" class="form-control" />
</div>
<div class="form-group">
<label for="recipient-name" class="col-form-label">Password:</label>
<input type="password" v-model="password" class="form-control" />
</div>
<div class="form-group">
<label for="recipient-name" class="col-form-label">Password:</label>
<input
type="password"
v-model="password_confirm"
class="form-control"
/>
</div>
</form>
<div>
<button type="button" class="btn btn-primary" @click="createUser()">
Save
</button>
</div>
</div>
</div>
</div>
</template>
<script>
import gql from "graphql-tag";
export default {
data() {
return {
username: "",
email: "",
password: "",
password_confirm: "",
};
},
methods: {
createUser() {
if (
this.username &&
this.email &&
this.password &&
this.password_confirm
) {
this.$apollo
.mutate({
mutation: gql`
mutation register(
$username: String!
$email: String!
$password: String!
) {
register(
input: {
username: $username
email: $email
password: $password
}
) {
jwt
user {
username
email
}
}
}
`,
variables: {
username: this.username,
email: this.email,
password: this.password,
},
})
.then((res) => {
console.log(res);
alert("User created Created");
});
} else {
alert("all fields are required");
}
},
},
};
</script>
In our newly created component, we added a form, implemented slight authentication and made our GraphQL query to create a new user.
After successfully creating the user, we will get back a response from our Strapi GraphQL containing the jwt
token which will enable you carrying out every authenticated user feature. You can get access to the token from the response object.
.then((res) => {
console.log(res);
alert("User created Created");
});
Conclusion:
Congratutlations, you've made it this far. By now, you should
- Be able to setup GraphQL in Strapi
- Be able to run GraphQL queries and Mutations using the Strapi playground, and within a Vue.js application using Apollo.
- Be able to carry out CRUD request using GraphQL
- Be able to Create an authentication system in Strapi using GraphQL
Now you have the basics. It's good enough to start building real-world projects. Remember to share your experience with the rest of the Strapi Community.
You can find the Vue.js project code base on GitHub here.