Prepare to receiving a FlashCard
We have transformed our sandbox into an actual element. This allows us to make HTTP calls. We could put that to good use because our server is ready to send us a flash card, we only need to ask.
In this chapter we will make a request for a flash card to our server, receive it and display it in our client.
Changing the model
Currently we assume we always have a flash card. Put since we are planning to receive one over the internet, things could go wrong. In order to be honest about this fact, we are going to change our model.
Currently we our model is an alias for FlashCard
type alias Model =
Maybe FlashCard
Let's modify it to reflect that we maybe don't have a flash card all the time.
type alias Model =
Maybe FlashCard
This breaks a few things that we need to fix.
view
The view
accepts a model so we need to adopt it to our new definition.
Earlier we could just take the flash card and display a meaningful representation. Now we first must make sure that we actual have a flash card and show a helpful message when we don't.
We can achieve this with a pattern match. Maybe
has two constructors, in our
case Just card
, where card
is a FlashCard
or Nothing
. So our view
functions needs to start with a pattern match like so
view : Model -> Html.Html Message
view model =
case model of
Just card ->
-- details below
Nothing ->
-- details below
The Just card
branch should do what we always did, changed to reflect the use
of the card
variable.
let
text =
case card.face of
Front ->
card.front
Back ->
card.back
in
div []
[ span [] [ Html.text text ]
, button [ Event.onClick Flip ] [ Html.text "flip" ]
]
When we don't have a flash card, i.e. in the Nothing
branch we need to report
this fact to the user.
div [] [ span [] [ Html.text "No flash card to show" ] ]
This wraps up our view
function.
update
Our update
function also accepts a model, so it needs to change as well.
Before we could just call the flip
function on our model when we received a
Flip
message.
Now, because it is wrapped in a Maybe
type, this will not work. The types
don't work out.
Luckily the Maybe
type has a convenient function called map
.
The signature of map
is
(a -> b) -> Maybe a -> Maybe b
which allows use to
Transform a Maybe value with a given function
I.e. allow us to apply a function to Maybe FlashCard
with out unpacking it
first. Our update function can therefore be
update : Message -> Model -> ( Model, Cmd Message )
update message model =
case message of
Flip ->
( Maybe.map flip model, Cmd.none )
Initial model
In our main
function we our creating a model by hand. At the moment it is just
a flash card, but it needs to account for the fact that maybe it isn't present.
The most dramatic change would be to pick Nothing
as our starting value.
Browser.element
{ init = \_ -> ( Nothing, Cmd.none )
, view = view
, update = update
, subscriptions = subscriptions
}
Verification
When you build the client and serve it from the server, this time you should see a message that there isn't a flash card.
Let's remedy that in the next chapter.