Remix Fundamentals

Multiple Forms Solution

Kent C. Dodds

Kent C. Dodds

Professional Trainer
Remix Fundamentals

Check out a free preview of the full Remix Fundamentals course

The "Multiple Forms Solution" Lesson is part of the full, Remix Fundamentals course featured in this preview video. Here's what you'd learn in this lesson:

Kent walks through the solution to the multiple forms exercise. A demonstration of Remix allowing the ability to name submit buttons is also covered in this segment.


Transcript from the "Multiple Forms Solution" Lesson

>> We are going to talk about multiple forums. So in our case, we want to be able to have a delete button and an update post when we're looking at a post and when we're on the new route. Then we just want to have the Create Post button.

So for the way that we're going to structure this, I wanna start with just the UI. And so we get all the buttons in the right spot and then we can make it function on the server. So instead of this p tag I'm actually gonna make a div that is display flex justify.

Let's see justify, or yeah, what is it space? Yeah, justify right. If I write or end yeah, that's what it is and then a gap of 4, okay. Cuz we're gonna have two buttons here now and this one is gonna be our delete button. So we'll have an is deleting variable that we'll create and this will say deleting otherwise delete post.

And for the deleting one, instead of blue, let's make it look red, so it looks dangerous and stuff. And then of course, we also only want that to render when we're on an existing post. If we're on a new post, I don't wanna render anything. So I'm going to add it is new post we'll render no otherwise, we'll render the button.

So we're gonna need to create that as new post variable here in a second as well. And then on this button we could actually create three separate buttons and just choose which to render but I'm gonna just reuse this one. Just because that's the way I did it and we're gonna stick with that.

So in this case, we want it to be disabled if it's creating or is updating. And then this one's gonna be a little bit tricky. We could do like a really funny looking, nested ternary thing here, and I tried it and I didn't like it. So what we're gonna do instead.

Isn't gonna say isNewPost so if we are a new post and isUpdating. Actually you know what? I don't remember exactly you, shoot. Yeah, I'm gonna have to reference this one too. [LAUGH] So a final seven slug. So I am cheating yes but I promise you'll be happier that I'm cheating than if I just tried to work this out myself, there we go.

So if we're a new post and we're in a creating state then we'll render creating otherwise we're under Create if we're not a new post then we'll render null. So we're not going to render anything for the creating one. If we are a new post then we won't render the updating state.

If we're updating then we'll say updating, otherwise we'll say update. So that just gets us in a good place for the button to say updating or creating based on the isNewPost and isCreating versus isUpdating state. Okay, great so the next thing that we need to do let's see yeah we'll do that here now is disambiguate between which transition we're doing.

So, if we come up here and we've got this isCreating we're just saying, hey we're in a creating state if we're submitting anything. If anything's being submitted I'm creating but that's not the case anymore, right? We have multiple forms on the page, multiple reasons we could be transitioning, with a submission, and so, now we have to have some way to disambiguate.

And so, we will need to say transition submission. So, we know what submission is being made, and the submission won't always be truthy. So we'll do this Elvis operator here to get the form data. So, if that transition, or if that submission exists, then the form data will exist and we can get Properties from that form data.

So what could we get? Well, we could get the post title that's not gonna tell us whether or not it's being submitted. We can get the Post Slug, also not gonna to be able to tell us and we can get the mark down that won't tell us either but there's one other thing that we can do.

Actually there are a couple of things but one thing that we can do to disambiguate and that is submit buttons like this can actually have a name and a value as well. This was a new thing for me when I started using Remix. But you can have a name, here we'll do the delete button first, you're gonna have a name that is delete.

Sorry we'll call it intent. So what did the user intend to do and the value be delete. So now you can look this up in the form submission to know what was the intent, which of these buttons did they click. So we can add a name on this one and we can say intent equals and we'll say if it is a new post, then this is gonna be create.

Otherwise it'll be update.
>> Do you mean value there?
>> You are exactly right. Thank you. [LAUGH] Value, there we go. So, all you need is either TypeScript or Peter and you'll be good [LAUGH] Thank you. So now we can get the intent and it the intent is create, then we know that the user is submitting the creation.

They've clicked on the create button and then we can do the same thing for our isUpdating and isDeleting. Come on co-pilot. Thank you. And then we'll do the same thing for isDeleting. And look they're all exactly 80 characters wide, that's fun. Okay, so now we know. Which of these three things the user is doing?

And down here, our stuff will hopefully I'll update. The last thing we need to do is create this isNewPost, and we should be able to actually render this thing. So I'll say isNewPost and we're gonna know that based on whether exists, so if there is no post on the data, then that means our loader returned to no.

We could also just get the params and say, here are the params new and if that's the case, then we can just do that as well. So, couple options there, but there's no posts and we are creating a new one. So now we can come over here, we get create.

And we get update and delete post. So that is working and we just need to make the backend actually function properly. Any questions so far? Okay, cool. So let's make the backend work now. For delete, that one's actually relatively straightforward. If we can just grab the intent from the form data.

And if the intent is delete then we'll just delete the post and in this case, we're gonna need the params slug. So let's grab the params and slug because our file name is dollar slug so that's why that pram works. So this delete post is gonna come from our model server right there.

And this is again, the params. Like could be undefined there's no way that TypeScript can know for sure that this is going to be defined. So we'll add an invariant rate appear invariant. For params.slug and slug not found, okay, cool. So now our delete button should work. Let's go ahead and try it just for the fun of it.

So delete and you saw it really quickly. It's a deleting data and then it deleted and redirected me where I wanted to go. Perfect, so now let's get rid of that. Now come down here and we just need to decide whether to update the post or create a post based on whether prams slug is new.

So if params slug is new then we will create the post otherwise we'll update the post with the title slug and markdown. And there we go. So now I can come over here and add, I don't know what's a good song? I can't think of a good song right now because I'm too busy thinking that I can't think.

I have a good song. So, Kryptonite, there we go. I knew that I was gonna be judged by any song that I said yeah, Jingle Bells. Okay, there we go. Updates like is required. Rats. Okay, so that's annoying let's fix that. I think that actually is broken in the finished.

Version so let's just fix that together here really quick. So we go to our slug the name here we've got a default value is the post slug and it's disabled. That's probably why it's not coming across. So but we wanna disable it because this is actually our ID of our post.

So you could probably fix this and make this blog platform have more features. But with the limited feature set that we have right now, what we're going to do is. Actually instead of using the slug here we'll use params.slug because they can't change that post slug anyway. Okay, so now, Kryptonite update, slug is still required.

Well, that is because at rats, that's because of this. So yeah, you all get it, we just fix it so we're not validating if we're updating yada, yada, yada. Cool so that is multiple forms. The basic idea is name and value on the button. That's that's pretty much it.

Another option is you can do it. Input hidden name whatever value whatever this was actually really common or you a lot of people will do type hidden really common back in the PHP days. Are you like I've got a to do list and I've got the ID of to do that you're checking off as a hidden input.

That's another option and this actually works nicely if you're integrating with a library like some form element that doesn't use regular HTML inputs and stuff. For its value and it's just expecting you to get an on change and do your own fetch or whatever. You could render a hidden input yourself with the value of that, whatever that's supposed to be.

So it will be submitted along with the rest of the form. So, that's actually a pretty fairly common solution to this problem as well. I really liked the button with the name and value. And the name intent is just convention and it's not even a remix convention and it's a KCD convention.

There you go. So I've also tried action and sub action. Intent is my favorite it's my least hated solution there.

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