Introduction to Elm, v2

Talking to Servers Solution

Richard Feldman

Richard Feldman

Vendr, Inc.
Introduction to Elm, v2

Check out a free preview of the full Introduction to Elm, v2 course

The "Talking to Servers Solution" Lesson is part of the full, Introduction to Elm, v2 course featured in this preview video. Here's what you'd learn in this lesson:

Richard walks through the solution to the Talking to Servers exercise.


Transcript from the "Talking to Servers Solution" Lesson

>> Speaker 1: Okay, let's go through these solutions. So [COUGH] we have two things to deal with here. The first is creating an HTTP request value that represents a post to /api/users. When this succeeds, by the way, let's go take a quick look, take off the optimize flag, at what we're building up to.

So we have once again broken the register function. And now there's just a lot of breaking stuff that used to work in this workshop. When I hit Sign up, nothing happens. I hammer on it all day and there's no HTTP request. It's really annoying. And that's because fundamentally, this command right here is not doing anything.

So once we replace these things with something that works, then actually, I can go back there and hammer on that button and it'll hopefully sign me up and create a user.
>> Speaker 1: Okay, so here's our request. So if we want to send a POST request to this, we're going to need to use this documentation right here.

So POST takes a string for the URL, so we can see that right there. Then it takes a JSON body. So we know the string that we want is gonna be /api/users, not /login. And we don't want debug.todo cuz that's just gonna crash, so that's no good. What we want instead is Http.send.

And the second argument is the JSON body. And we got one of those right up here, that's requestBody.
>> Speaker 1: Okay, and what else does this thing expect? Then the final argument is what's the decoder of a, and that'll give us back a request of a. So since we want a request that's going to produce a viewer, we want to find a decoder viewer, which conveniently, we've already got right here in responseDecoder.

So responseDecoder, okay. So at this point, I can pause and just see if that compiles. It does not because I did something wrong. Yes, because I wrote Http.send instead of Very different functions those. Okay, much better, compiled 2 modules, successful. Okay, so now we've got our request, and now we're gonna use Http.send to create this command based on using the request, and also a message that can accept results of both the two possibilities.

Either the HTTP request failed or that the HTTP request succeeded. So if I look at the docs for send, we can see that it's first expecting a function that takes a result error a, and then returns a message. Then it wants a request of a, and it's gonna give back a command of message.

Notice by the way the lowercase m here. This is a type variable. It's just we're choosing the type variable name Msg to represent the fact that this is a message type. So what we want is a variant function. Basically, that's going to say, given a result, I will give you back a message that encapsulates that result or wraps that result.

Okay, there's a hint as to which message we should use. Look at that one. I wonder which one has to do with HTTP. It's called CompletedRegister, and it's got exactly what we want. It's either an Http.Error or it's a viewer value. All right, so based on that, we're gonna say Http.send.

And that was the first argument to Http.send was that, that function from Result Error a to message. And a in this case is based on the type parameter of the request, which is Viewer. So since CompletedRegister takes Result Error Viewer, that's exactly what we want. So we'll just pass that right in, CompletedRegister.

And finally, it wanted the request itself. So we can give it that, which is request. And we're done. Let's confirm that that compiles, which it does. Also, if we wanted to, we could do this in the pipeline style, like we showed on the slides and do it like this.

>> Speaker 1: So this would also work. Do an to /api/users with this body and this decoder. And then send the result using that message. Now we'll also compile. Okay, it compiled, but did it actually work? Let's find out. Now when I hammer on this,
>> Speaker 1: Hey, success, we now are able to sign up successfully, fantastic.

>> Speaker 2: Do you have a set guideline for where you're putting decoders versus your API requests versus, is it common to see it in an update, an all in one and a decoder somewhere else?
>> Speaker 1: Great question. The question is organizationally speaking, is it common to put your decoder right there in the update?

No, I would say it's more common to put it with the data structure. So it's a lot more common to have, for example, if we look in, so Viewer, there actually is a module called Viewer, which holds all of the information for viewers. As it happens, there actually is a Viewer decoder in here, which we didn't use for this exercise directly, because I didn't want you to have to go hopping around through different modules to find it.

But fundamentally, that's a more typical pattern. So usually, you'll see something like this, like Viewer.decoder, which means go to the Viewer module, get the decoder value out of that. And that's usually where you'll store these things.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now