Update todos - mutation

In this part of the tutorial, you will learn how to update existing todos by using GraphQL Mutations.

Let's define a graphql mutation to update todo.

mutation toggleTodo ($id: Int!, $isCompleted: Boolean!) {
update_todos(where: {id: {_eq: $id}}, _set: {is_completed: $isCompleted}) {
affected_rows
}
}

You will also need to pass in the values for the variables.

Try this mutation in GraphiQL against the application database to see what the response looks like.

Let's now integrate this graphql mutation into our elm app.

We will construct a GraphQL Mutation to update a private todo and integrate it with the elm app.

Import dependencies

Lets import the types, utility functions generated by elm-graphql into our app and construct a GraphQL query

Open src/Main.elm and add the following code:

import Hasura.InputObject
exposing
( Boolean_comparison_exp
+ , Integer_comparison_exp
, Todos_bool_exp
, Todos_insert_input
+ , Todos_set_input
, Todos_order_by
, buildBoolean_comparison_exp
+ , buildInteger_comparison_exp
, buildTodos_bool_exp
, buildTodos_insert_input
, buildTodos_order_by
+ , buildTodos_set_input
)
import Hasura.Mutation as Mutation
exposing
( InsertTodosRequiredArguments
, insert_todos
+ , UpdateTodosOptionalArguments
+ , UpdateTodosRequiredArguments
)

Construct GraphQL Mutation

We will be constructing a GraphQL mutation as above

makeMutation : SelectionSet (Maybe MutationResponse) RootMutation -> String -> Cmd Msg
makeMutation mutation authToken =
makeGraphQLMutation authToken mutation (RemoteData.fromResult >> GraphQLResponse >> InsertPrivateTodoResponse)
+updateTodoStatus : Int -> Bool -> SelectionSet (Maybe MutationResponse) RootMutation
+updateTodoStatus todoId status =
+ Mutation.update_todos (setTodoListUpdateArgs status) (setTodoListUpdateWhere todoId) mutationResponseSelection
+
+
+setTodoListSetArg : Bool -> Todos_set_input
+setTodoListSetArg status =
+ buildTodos_set_input
+ (\args ->
+ { args
+ | is_completed = OptionalArgument.Present status
+ }
+ )
+
+
+setTodoListUpdateArgs : Bool -> UpdateTodosOptionalArguments -> UpdateTodosOptionalArguments
+setTodoListUpdateArgs status optionalArgs =
+ { optionalArgs
+ | set_ = Present (setTodoListSetArg status)
+ }
+
+
+setTodoListValueForId : Int -> Integer_comparison_exp
+setTodoListValueForId todoId =
+ buildInteger_comparison_exp
+ (\args ->
+ { args
+ | eq_ = Present todoId
+ }
+ )
+
+
+setTodoListUpdateWhere : Int -> UpdateTodosRequiredArguments
+setTodoListUpdateWhere todoId =
+ UpdateTodosRequiredArguments
+ (buildTodos_bool_exp
+ (\args ->
+ { args
+ | id = Present (setTodoListValueForId todoId)
+ }
+ )
+ )
+
+
+updateTodoList : SelectionSet (Maybe MutationResponse) RootMutation -> String -> Cmd Msg
+updateTodoList mutation authToken =
+ makeGraphQLMutation
+ authToken
+ mutation
+ (RemoteData.fromResult >> UpdateTodo)

Add Data Types

Lets add new data types required to perform this operation

type alias TodoData =
RemoteData (Graphql.Http.Error Todos) Todos
+type alias UpdateTodoItemResponse =
+ RemoteData (Graphql.Http.Error (Maybe MutationResponse)) (Maybe MutationResponse)

Add new Msg type

Lets add Msg types required to perform this operation

type Msg
= EnteredEmail String
| EnteredPassword String
| EnteredUsername String
| MakeLoginRequest
| MakeSignupRequest
| ToggleAuthForm DisplayForm
| GotLoginResponse LoginResponseParser
| GotSignupResponse SignupResponseParser
| ClearAuthToken
| FetchPrivateDataSuccess TodoData
| InsertPrivateTodo
| UpdateNewTodo String
| InsertPrivateTodoResponse (GraphQLResponse MaybeMutationResponse)
+ | MarkCompleted Int Bool
+ | UpdateTodo UpdateTodoItemResponse

Handle new Msg types in update

UpdateNewTodo newTodo ->
updatePrivateData (\privateData -> { privateData | newTodo = newTodo }) model Cmd.none
+ MarkCompleted id completed ->
+ let
+ updateObj =
+ updateTodoStatus id (not completed)
+ in
+ ( model, updateTodoList updateObj model.authData.authToken )
+
+ UpdateTodo _ ->
+ ( model
+ , fetchPrivateTodos model.authData.authToken
+ )

Update render functions

viewListItem : Todo -> Html Msg
viewListItem todo =
li []
[ div [ class "view" ]
[ div [ class "round" ]
- [ input [ checked todo.is_completed, type_ "checkbox", id (String.fromInt todo.id) ] []
+ [ input [ checked todo.is_completed, type_ "checkbox", id (String.fromInt todo.id), onClick (MarkCompleted todo.id todo.is_completed) ] []
, label [ for (String.fromInt todo.id) ] []
]
]
, div
[ classList
[ ( "labelContent", True )
, ( "completed", todo.is_completed )
]
]
[ div [] [ text todo.title ]
]
, button [ class "closeBtn" ]
[ text "x"
]
]