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.
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 MutationCreate, MutationUpdate 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!
Those mutations can now be tested with GraphiQL.
The create mutation:
The deleteUser mutation:
The update mutation:
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).
createUser, deleteUser 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:
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:
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:
This means that Apollo has its own Redux Store!
Here it is:
Let’s get back to the good solution.
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:
- Mutations are going to be run
- The result from those mutations will be acquired
- This main Users Query will be read then modified
- 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:
All 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:
- Using a GraphQL mutation document
- Passing the variables
- Updating Apollo’s Redux Store
Here is the final result:
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.