Post requests with PureScript Affjax and Argonaut


In this post I will explain how make a simple ajax call in PureScript, using Affjax and Argonaut.

For this example I’m going to use http://jsonplaceholder.typicode.com/ as my API endpoints. We will make a POST call to the /posts endpoint to create a new post.

A post has these fields: title, body, userId and id. To create a new one, we’ll have to send an object containing the first three fields to the appropriate endpoint.

We can model our data type:

data Post = Post { id :: Maybe Int
                 , title :: String
                 , body :: String
                 , userId :: Int
                 }
                 
post1 = Post { id: Nothing, title: "title", body: "body", userId: 20 }

We have our data, now we only need to find out how to send it to our endpoint! Affjax documentation tells us that:

When sending data in a request the Requestable class enables automatic conversion into a format that is acceptable for an XHR request. Correspondingly there is a Respondable class for reading data that comes back from the server.

We need to implement a Respondable and a Requestable instance for our data type. The documentation doesn’t tell us much more, and the type signatures are a little cryptic for a beginner.

Luckily, the instances are already defined for Json, so we can look at Argonaut for rescue!

We will need to implement decodeJson and encodeJson for our data type.

instance decodeJsonPost :: DecodeJson Post where
  decodeJson json = do
    obj <- decodeJson json
    id <- obj .? "id"
    title <- obj .? "title"
    body <- obj .? "body"
    userId <- obj .? "userId"
    pure $ Post { id, title, body, userId }

instance encodeJsonPost :: EncodeJson Post where
  encodeJson (Post post)
    = "id" := post.id
    ~> "title" := post.title
    ~> "body" := post.body
    ~> "userId" := post.userId
    ~> jsonEmptyObject

Now we’re ready to make our ajax call:

main :: forall e. Eff (err :: EXCEPTION, ajax :: AJAX, console :: CONSOLE | e) Unit
main = void $ launchAff $ do
  res <- post "http://jsonplaceholder.typicode.com/posts" (encodeJson post1)
  liftEff $ log $ "response: " <> res.response

Related Posts

Resizing and moving windows in Doom Emacs

Setting up TabNine on Doom Emacs

The correct docker-compose setup for Wordpress and Nginx

Adding a newline after a comment block in Doom Emacs

PureScript Date and Time guide

Adding live css and js reload to Yesod

A quick overview of Purescript package managers as of October 2018

Optional elements and properties in Halogen

Simple AJAX in Purescript

Automatically adding (or removing) a prefix to a record labels in Purescript