Implementing GraphQL using Apollo in an Ionic Application: CRUD

Apollo for Angular is quite new so this article will be quite experimental and (I hope) it might change after the release of the incoming apollo-client 2.0.
Thanks to Angular, Ionic applications benefit from two-way data bindings and this feature will affect how our CRUD is built.
As starting point, we take the previous introduction article on Apollo and GraphQL and start by setting up the server side.

Server Side

Until now, we have only seeing how to access the data through Queries. In order to make some modifications, Mutations are used.

Let’s start by adding the mutations to our Schema at the end of the user.schema.js file:

Next step, creating the following MutationCreateMutationUpdate and MutationDelete objects.

Starting with MutationCreate:

We are going to return an array of users.
This mutation will receive the user’s name as a string.
As usual the resolve property is where the work is done. A new user object will be pushed in the USERs array.
The id will be randomly created and the name will be the one we will get from the client. At the end, we return the list of users to the client.

The MutationUpdate object is slightly more complex:

The id and newName are received.
The built-in filter method is used on the USERs array to acquire the corresponding user. This method returns an array so we just grab the first result.
This user will have its name replaced by the one we get from the client.
As usual the new USERs array is returned to the client.

Finally, the last mutation:

Once again the filter method is used. This time we grab every users except the one matching the ID to delete.

We are now done for the server side.

We can now directly test our mutations with GraphiQL!

GraphiQL tests

Those mutations can now be tested with GraphiQL.

The create mutation:

ionic graphql node apollo CRUD create mutation graphiql

The deleteUser mutation:

ionic graphql node apollo CRUD delete mutation graphiql

The update mutation:

ionic graphql node apollo CRUD update mutation graphiql

The Ionic Application

Let’s start by changing the home.ts file:

A Response can have more information now. The mutations results will be located in a field named after the mutation (deleteUser, create or update).

createUserdeleteUser and updateUser are constants that will contain the GraphQL mutation documents.

The syntax is as follow:

A small detour

Before diving into the real solution, let me show you one interesting thing about Apollo and Ionic.

First the ngInit is redesigned:

Using the data from the subscribe method will lead us to a surprise later 😉. The users from the data response are acquired and the data property is updated.

Following with the home.html file:

The users names are now editable through a simple input thanks to the traditional ngModel and a button will trigger the updateUser method.

The updateUser method is as follow:

The mutate method is used with the updateUser GraphQL document, the id and newName variables. We then subscribe and update the data with the mutation’s result.

Everything should be good right?

Running the Ionic application:

ionic graphql node apollo CRUD not changing

Well that’s that’s odd right? Our data bindings aren’t working properly!

Let’s see if we can act on the data property when the input changes in the HomePage:

By passing the user’s id and the $event, we will have enough information.

For now, we only modify the first item’s name:

Here is what we get:

ionic graphql node apollo CRUD read only

A new error:

Cannot assign to read only property ‘name’ of object ‘[object Object]’.

Our data are read-only! The information returned by a GraphQL Query are supposed to be read, not modified.

If you have followed the latest tutorials on Redux, you should be familiar with this icon in Chrome:

ionic graphql node apollo CRUD store icon

This means that Apollo has its own Redux Store!

Here it is:
ionic graphql node apollo CRUD store

Let’s get back to the good solution.

Subscribe to my mailing list to get access to a Free 7-day Ionic 3 introduction email course!
100% Privacy. I'll never spam you!

The Good Way

The correct way to acquire Apollo’s Redux Store data is as follow:

The main Users query is watched and we get the data from this query.

The concept is simple:

  1. Mutations are going to be run
  2. The result from those mutations will be acquired
  3. This main Users Query will be read then modified
  4. The UI will automatically get updated because we are watching the changes

We put back the correct ngFor:

Handling multiple inputs, the state of the data on the server and Apollo’s Redux Store at the same time can be tricky.

A new Component will be used to update a user one at a time.

This one is from a previous tutorial on the ngDragDrop project:

This Component will receive the user from its parent: the HomePage.
Those information will be copied into a new property by using the built-in assign method. When the user leaves the input, this component will tell the HomePage to update the corresponding user.

Here is the data copy:

ionic graphql node apollo CRUD data copyAll we need now is adding the component to the app.module.ts file:

And using it in the home.html:

While we are here, let’s add the buttons for the create and delete methods, here is the final home.html file:

One input with an ngModel to stock the newUsername, coupled with a button that will trigger the createUser method using this newUsername.

One button will be displayed for each <ion-item>. Tapping on it will trigger the deleteUser method using the user’s ID.

We need to change the updateUser method:

The user is received from the XEditable Component, it has everything up-to-date.
The mutate method from the apollo property will update the data on the server side. In order to update the data in Apollo’s Redux Store, it is recommended using the update field.
We acquire here the store and the data from the mutation.

Two important methods are used here: readQuery and writeQuery.
The readQuery method allows us to access the current data from the Users query, it’s the information that we started watching earlier.
We stock it in a variable and modify the users property with the mutation’s result. Finally by using the writeQuery, the store updates the information returned by the Users query and the UI is updated.

What’s left now: the create and delete features.

This is a piece of cake.

Those two methods are as follow:

They do the same thing:

  1. Using a GraphQL mutation document
  2. Passing the variables
  3. Updating Apollo’s Redux Store

Here is the final result:

ionic graphql node apollo CRUD final result

BONUS CONTENT
Enter your email address in the box below to get access to this tutorial (and others) source code.

Conclusion

Queries aren’t Mutations.
The data returned by a Query is read-only so be prepared to create a writable copy. GraphiQL is once again very helpful for testing the mutations before diving into the Ionic application.
Once we understand how Apollo works, it become a bit repetitive. It’s mainly about watching a query and updating it once new information are available.

2 Comments

  1. September 12, 2017    

    excellent man…i have one query..what does mutate keyword do in the following code
    this.apollo.mutate({

    • Matthieu Drula Matthieu Drula
      September 12, 2017    

      Thanks Albert.

      The mutate keyword triggers a specific mutation. We use it to trigger the mutations we tested in the GraphiQL test part.
      There are other keywords like: query or watchQuery for triggering a Query or subscribe for starting a subscription (we will see this one later with Apollo v2).

Leave a Reply

Your email address will not be published. Required fields are marked *

3 Shares