Qwik for Instant-Loading Websites & Apps

Posting Data to the Server

Miško Hevery

Miško Hevery

Qwik Creator (Previously Angular)
Qwik for Instant-Loading Websites & Apps

Check out a free preview of the full Qwik for Instant-Loading Websites & Apps course

The "Posting Data to the Server" Lesson is part of the full, Qwik for Instant-Loading Websites & Apps course featured in this preview video. Here's what you'd learn in this lesson:

Miško adds an edit page for a contact record. The edit page posts the contact data to the server. Missing data errors are added to an errors object and displayed back in the client form.


Transcript from the "Posting Data to the Server" Lesson

>> So now we have a list here. This is interactive, right, so you can search for it on the client. We get this back from the server, we can have the details over here. I think the next thing to do is to kinda have an Edit button in here, right?

So to get an edit, really what we want is, We probably want to have a link here, edit, Something like this, and we wanna say /, And why is it red? I can not type it in there, okay, good point. Just put it in here. All right, [COUGH] so now we have an edit link, right?

And that gets us to another route that, of course, we don't have. So let's make that one. And that one should be pretty straightforward. So I'm just gonna copy what I have right now, the whole page. And actually, I'm just gonna make a new route here. And so, it is, edit/index.tsx, I paste it in there and I'm also have to copy the CSS in here, okay?

And so, now our edit route, and of course, Vite has to be restarted. Yeah, so this one also has a wrong path. Sorry, it was it was not Vite this time. Okay, so now, the edit takes us the same exact point, and so we can change things. First of all, we probably want to, There needs to be a form, we have to change everything to be editable, right?

So we need a form on it. So let's do that. First of all, this would be cancel, and now it just goes here, right? So now, if we do edit, cancel gets us to the main route, edit goes into the edit route, and then we have to change all this stuff.

So wherever it says c.name, really we have to change it to input. Right, so now I can edit this particular bit. And let's do the same exact thing for the other bits as well. So that we have to do this for name, we have to do this for Twitter.

So that would be, But this will be Twitter. This will be, what it would be? c.twitter. All right, probably make those inputs bigger. And this is where my CSL is gonna fail me, so I'm just gonna do with, I don't think I can do 100%. I think I just need to do 500 pixels, it's gonna be way too much, yes.

Somebody who could be better at CSS than I can probably make it auto. I think you have to set up a flexbox, we could do that, but I think it's gonna be missing the point, yes.
>> A related question, could you use Tailwind CSS with this?
>> Yes, you can, again, if I go to npm run qwik add, notice Tailwind (styling) is one of the options that's over here.

And Vanilla Extract is the other one that I think is even better than Tailwind. So we could do that, but I wanted to keep the things simple and straightforward for now, not to introduce too many concepts. So we're kind of staying away from that for now. Plus, I haven't learned how to use that yet.

So, [LAUGH] that was done by the community. Okay, so now, this is the details, the edit gives us the cancel, we have over here. And so, let's say I wanna actually submit this. So I wanna make it into a form. So one of the things we need to do now is we need to turn it into a form.

So now we're gonna say this is a form, and this whole div goes in. And this form is gonna require a button, that's gonna be a Save button. And the form is going to be posted somewhere. Well, it's going to be posted to itself, so I don't actually have to do anything, but I do have to say method is POST on it.

So now I have a Save button, and if I change anything, if I hit Enter, it's gonna post the form back into itself. Except, the system is gonna complain because we didn't do anything yet, right? Yeah, it just didn't render. Okay, the problem is we don't have a POST handler, and so the system just kinda crashed.

You posted over here and you didn't tell me what to do, so I'm dying. So let's write a onPost method. And again, we're gonna create a request handler. [COUGH] And in this case, we're gonna do something slightly different. The basic idea is we're just gonna extract, let's see, what does it, no.

You're trying to be helpful, but you're actually wrong on this one, so we'd say request. And let me just leave this, request.formData, const data=await. So this is how we get the form data. And here we're gonna do some checks on the form data. So if isValid, oops, Then we're gonna do something, otherwise we're just gonna return something, which is gonna return the data again.

The isValid, I'm gonna declare here for now, and we will get back to it in a second. You're not helping. So data is right, okay, so that's okay. So data, and so we have to say contact. Contact is, and it's the contact, if it's the contact, isValid, contact.

And for now, we're just gonna say return false. Export function, I guess this export is unnecessary over here. Let's see, formData, yep, and then contact. So, contact has ID, yep. And then it has name. This is, again, one of those areas that we're gonna have a more type-safe solution in the future.

Wow, autopilot, you're good. Okay, we're gonna have some more better solution in the future. And for here, I'm just gonna ignore this part for a second. And for now, we're gonna just basically fail it in every single case. But what that means now that I can go change it, hit Enter, and the form data is still there.

Notice what happened, I've changed the data, we posted it to the server. The server, because it said, for whatever reason, it decided it's invalid, right? We haven't implemented that thing, it just returned the data back to us. And because it returned the data back to us, we got the data back as an endpoint, and we just re-rendered it back the way it was.

And so, we now have an easy way of kind of double-checking it. But let's change this slightly. So, let's say that here we say contact, and here we're gonna say errors. And right now we have no errors. So now, instead of Contact, we say it's a ContactForm. And so, let's declare type interface ContactForm as the contact, and then errors.

Which is going to be, I'm gonna cheat again because I don't remember. Okay, let me see if I can figure it out, hold on. What we want, we want a object that is string, which is keyof, no, key of, is it one word, two words? Key of contact?

So we wanna have the same contact. Key in, no. Anybody remember how to do this in TypeScript? Keyof [INAUDIBLE] any type, key of Contact, yeah, okay, hold on. P in keyof, okay, sorry, it's P in keyof, there we go. So now we're saying, look, we have the same set of keys as you had before, but they're optional.

So for each property in contact, we have now an error property inside of the errors. Does that make sense? Okay, so we originally sent it with no errors. And now [COUGH] let's say that we go and validate this thing. And so, we have the contact, and so we need to have the whole data, so, const data =, contact: contact, and errors is this.

And then so we wanna verify isValid, data, name, so, isRequired, how about that? So we're saying that the name, and then this becomes object. Actually, let's do contact. And then the error goes into data.errors, perfect. Errors, and that's, Record of string, string. And then, sorry, field, which is a, let's just say it's a string for now.

So now what we're gonna do is we're gonna say it is if. So we're saying, if contact name has a string, sorry, field, then if it doesn't have, rather, if it doesn't have, then errors field should say required. And then this should say it's not a string, this is a keyof contact

>> Your type needs to be field, not filed, 41.
>> Thank you, so now we're saying, hey, double-check that this is required, right? So now, what is this complaining about? This doesn't return. All right, so this needs to return, true, otherwise return false, right? [COUGH] So now we're gonna fall down this particular path.

isRequired, so isRequired, so, no, isRequired becomes true when everything's okay. Otherwise it falls through here, and we're gonna get back data. And so now what you're gonna get is, Here in this form, return. Oops, okay, so now we can extract const c =, Okay, and so now, we can say if data.error, let's just return const data.errors.

We can say errors, and so errors.name, perfect. Let's just do it for name for now. So now if, Data contact, what were you complaining about? No, yes, because of contact. Form, yeah. Cannot read properties of undefined, why is it trying to be undefined? Okay. Data is undefined because, Okay, There we go, so now if I delete this, Okay, let me simplify this code because I'm confused on it.

Okay, required, right here. Sorry, I just didn't see it, it's right here. So actually, let's do it span, span, and then go to, .error, color: red, there we go, okay. So, when I type in something, it's fine. If I delete it, then it says required. I'm gonna pause it because I think I went through it a little too fast.

So let's go from the beginning. When we originally get it, we push in the contact property, but we also push in an empty object that contains the errors, right? At the beginning there are no errors, because you're editing something that is already fine. [COUGH] And then when the user goes and edits, this form posts back to the same URL.

And this onPost extracts the data from the form, and then verifies if my name is present. If my name is not present, it inserts the flag into the errors, right? And that flag is what then prints out this particular error. So here we should probably say, The, Field, Is required, right?

So now, it says the name is required.

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