6.10

Deleting a Resource Using DELETE

Deleting a post takes less effort compared to updating it. The first thing we need to do is add a delete button next to each row in Views/List.elm.

viewPost : Post -> Html Msg
viewPost post =
            .
            .
            , td []
                [ a [ href postPath ] [ text "Edit" ] ]
            , td []
                [ button [ onClick (DeletePost post.id) ]
                    [ text "Delete" ]
                ]
            ]

When the Delete button is clicked it sends the DeletePost message to the Elm Runtime. Let’s add that message to the Msg type in Types.elm.

type Msg
    .
    .
    | PostUpdated (Result Http.Error Post)
    | DeletePost PostId

Add a new branch to the update function in State.elm to handle the DeletePost message.

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        .
        .
        PostUpdated _ ->
            ...

        DeletePost postId ->
            case findPostById postId model.posts of
                Just post ->
                    ( model, deletePostCommand post )

                Nothing ->
                    ( model, Cmd.none )

The code for handling DeletePost is very similar to the one we wrote in the previous section for handling the SubmitUpdatedPost message.

SubmitUpdatedPost postId ->
    case findPostById postId model.posts of
        Just post ->
            ( model, updatePostCommand post )

        Nothing ->
            ( model, Cmd.none )

Now add the definition for deletePostCommand and deletePostRequest to the bottom of Rest.elm.

deletePostCommand : Post -> Cmd Msg
deletePostCommand post =
    deletePostRequest post
        |> Http.send PostDeleted


deletePostRequest : Post -> Http.Request String
deletePostRequest post =
    Http.request
        { method = "DELETE"
        , headers = []
        , url = "http://localhost:5019/posts/" ++ (toString post.id)
        , body = Http.emptyBody
        , expect = Http.expectString
        , timeout = Nothing
        , withCredentials = False
        }

Once again, we’re using Http.send instead of RemoteData.sendRequest to create a command for deleting a post. To delete a resource on the server, we need to use the DELETE method. The url for deleting and updating a resource is exactly the same. The only information a server needs for deleting a resource is its URL. That’s why we’ve assigned Http.emptyBody to the body field.

json-server responds with {} — an empty JSON object — when asked to delete a resource. Since there’s nothing to decode inside an empty JSON object, we passed Http.expectString instead of Http.expectJson to the expect field. Because of this, the return type of deletePostRequest is Http.Request String. Whereas the return type of the updatePostRequest function from the previous section is Http.Request Post.

deletePostRequest : Post -> Http.Request String
updatePostRequest : Post -> Http.Request Post

Next we need to add PostDeleted to the Msg type in Types.elm.

type Msg
    .
    .
    | DeletePost PostId
    | PostDeleted (Result Http.Error String)

Add a new branch to the update function in State.elm to handle the PostDeleted message.

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        DeletePost postId ->
            ...

        PostDeleted _ ->
            ( model, fetchPostsCommand )

Once again, to keep things simple we are ignoring errors in PostDeleted _ -> branch. Properly handling errors is left as an exercise for the readers. After a post is deleted, we want to refresh the list view by refetching the remaining posts. That’s why we’re returning a command to fetch posts. The only remaining step is to expose deletePostCommand in Rest.elm and State.elm.

module Rest exposing (fetchPostsCommand, updatePostCommand, deletePostCommand)
.
.
module State exposing (..)
.
.
import Rest exposing (fetchPostsCommand, updatePostCommand, deletePostCommand)
.
.

Run elm-live from the beginning-elm directory in terminal using the following command if it’s not running already.

$ elm-live PostApp/App.elm --pushstate

Go to the list view (http://localhost:8000/posts) and delete the first post. It should disappear from the list view and server/db.json as well.

{
  "posts": [
    {
      "id": 2,
      "title": "http-server",
      "author": {
        "name": "indexzero",
        "url": "https://github.com/indexzero"
      }
    }
  ],
  "comments": [],
  "profile": {
    "name": "typicode"
  }
}

json-server also deleted the following comment that was associated with the first post. Notice how the comment below uses postId field to tie itself to the post we just deleted.

{
  "id": 1,
  "body": "some comment",
  "postId": 1
}

This is a common behavior on the server side. When a resource is being deleted, it’s likely that the dependent resources also get deleted.

Summary

In this section, we learned how to delete a resource using the DELETE HTTP method. Compared to other operations we have covered so far — fetching and updating — deleting a resource is relatively easy. We don’t need to encode or decode any JSON value. All we need to do is specify the location of the resource.

In the next section, we’ll learn how to create a new resource by sending a POST HTTP request.

Back to top

New chapters are coming soon!

Sign up for the Elm Programming newsletter to get notified!

* indicates required
Close