TypeScript and Vue 3

Creating an Edit Page Solution

Ben Hong

Ben Hong

TypeScript and Vue 3

Check out a free preview of the full TypeScript and Vue 3 course

The "Creating an Edit Page Solution" Lesson is part of the full, TypeScript and Vue 3 course featured in this preview video. Here's what you'd learn in this lesson:

Ben walks through the solution to the creating an edit page exercise which can be located on the 11-finish branch.


Transcript from the "Creating an Edit Page Solution" Lesson

>> This is kind of a culmination of a lot of things that we've been doing. So I know that it's been a long day, but I figured a bit of a challenge might be fun to get people trying out something where there's not a base waiting for you.

So what I've gone ahead and done is, I've gone ahead and duplicated the new dishForm and just made it the editdishForm. And so for the sake of demoing it, we could do the routes and everything. But for the sake of time, I just kind of wanna show how it works.

So to make sure everything works, so let's go ahead and make sure that, let's see. We're gonna go inside of the dish page. And so this time we're gonna actually change show new form. Show new form actually is no longer correct as far as what it is. Really what show new form should be is a series of values.

And so for now we're just gonna leave it as a string though. But basically it should either be new, or it should be empty, or it should be edited. That's kind of what I'm thinking. So actually what we can do though, we're here to type stuff out. So let's go ahead and do a show.

We'll call it a ShowState. ShowFormState. And this will be, basically we'll have it empty. It can be new, or it can be edit. And so then we'll type that to ShowFormState. And then by default, it will be an empty string. So this is good. We have some things to break though, so let's go ahead and do some things.

So hideForm, basically when we ever we hide the form, we want to go back to empty string, we don't need it to show anything. So that's taken care of. And then here, now if the new query is showing, we don't want it to be true, right, this is where TideStrip's helping us.

It's saying, what do we need it to be? We need it to be new. And then now that I actually know this, I'm just gonna jump the gun too and say that if we get an edit query on it, then showNewForm.value is going to be edit. And so now that I think about it, showNewForm as a whole is actually the wrong name.

So we're gonna rename all showNewForm to just showForm. And so I just did that with the multiselect. And so now that we have that, let's see. So we'll go through showForm, okay. So when we click on this, we are going to, showForm is going to be equal to new.

That's what we're going to do that will let us actually toggle the new form. And then we'll scroll down. Okay, so we have here, filter item. Okay, so now this is a little bit tricky because after all, our editForm doesn't actually show up in this, it actually lives in dishCard.

So now we gotta dive into dishCard and we gotta think, okay, well, what we need to do is, we need to actually emit an edit event. That's what we really need to do. So let's go ahead and define that, shall we? So we have another event that we're gonna emit.

And this will be a update or edit-dish. Let's just call it what it is. And it's not alphabetical, so I'll swap that real quick. And then we'll patch up the dish that we want to edit. That's basically what we'll do. So then with that, we know that happens.

So now we can go ahead and say, let's see, I'm gonna go ahead and similarly construct a dish. We'll create a new function. And then this will emit what we'll see the C + Cmd + Space or control space, edit-dish, perfect props.dish, that looks good. And now we have our Edit button here, so let's go ahead and add the click.

And when we click it, we're gonna run edit-dish, and that is actually everything we need. So once we have that, we can jump back up to the page. And the page now will actually be able to listen for this event. So we have the edit-dish. And so what we can do here is, we're gonna do, let's just name edit-dish again, and maybe edit-dishForm, that is a little bit cleaner.

So then here now we can do [SOUND] beneath here makes the most sense, edit-dishForm. And we have a payload, which is of type Dish. And so now what we're gonna do though is we're gonna say, showForm.value is going to be edit. And the reason this is valuable is because we need now to actually toggle that component that we just grabbed the edit-dishForm.

So again, there's gonna be some repetition in here. And I know that that's always a little bit tricky to manage sometimes, especially if, see, we're used to the, do not repeat yourself context. But it is helpful sometimes just to focus on getting something out the door first rather than sort of optimizing for it.

So this is v-else-if. So you can see here now I've updated the logic so that basically if showForm is new, show the new dishForm. Otherwise if the showForm is edit, show the EditDishForm, and then otherwise we will show the thing. And so the key thing here though is, we're gonna need to actually pass this into this component.

So to make sure this works, silly me, this is wrong. This need at least, I'll just strict equal that. Okay, so to prove that this works, I'm gonna go ahead and just say, edit Name right here, and then we'll go ahead and check to make sure everything worked.

So where's my app? I think it closed it. Okay, let me pump this up. Okay, we have our dishes. Whoop, missing semicolon, dishes page. Let's find out. Dishes page. I guess that was an error that we saw earlier. Else, silly me, else if, there we go, that's good now.

All right, so now there we go. All right, so we have the restaurants, we have the dishes, and now if we click on Edit. Okay, so Edit Name is appearing, we have the right component coming in. So now what we need to do is, we actually need to fetch the ID.

So how are we gonna do that? Well, what we can do is, we can probably, just for now, let's see, how are we checking this inside of this page? Currently, we have a showForm dishList. Okay, so we know for a fact that editDish is gonna tell us the ID, that's really what we ultimately need.

So what I'm gonna do is, we're just gonna create a ref that we're gonna track for now called edit Dishid, and this is gonna be a ref that's just a string. And what we're gonna want to do then i, s on the point of edit, we will do editDishid.value = payload.id.

And we know that it happens because we know that dish itself has an ID property. So again, once again, typing to the rest of you for this. Once we have this, what this tells us is, inside of editDishForm, we can have a prop that takes in that specific ID, right?

So I can say, defineProps. And then the inside of defineProps, we'll take a, I don't wanna call it ID cuz it'll conflict with a HTML specs. That's usually a rule I tried to establish whenever I write anything. So we'll just call it dishId, and this will be basically a string.

We don't need to be any more complicated than that. So now that we've defined the props here, we should be able to, inside of our editDish component, there we go. We can then say, dishId is going to be equal to editDishId, just like that. And then I've realized it's not always gonna be true, we won't always have one.

So inside of our editDish, we're gonna just make it optional so that it doesn't yell at us. Okay, that should do the trick. And then to make sure this works, we'll go ahead and render out the edit or dishId, I think it's what I called it? Yeah, dishId is what I called it.

Okay, let's see if this works at all. So if I click Edit, Refresh, Edit, there we go. There's our ID. If we go back, I didn't turn away to cancel it, that's totally fine. Okay, so now that we have our ID, what do we need to do? Okay, we need to actually get the thing from the store.

And the way we're gonna do that is, inside of stores, something you might not be aware of is that, getters can actually receive an argument. So we can basically pass in an argument to get to basically do a little bit of fetching. So in this case it will be, getDishById.

And so we know that we get the state by default, right, from our, woo, that's wrong, there we go. And then what we're gonna return though is, we're gonna return a dish, that's something that's important. So what we're gonna do is, we're gonna return the state.list.filter, and we're gonna filter what?

We're gonna filter every dish inside of here. And dish.id should be equal, sorry, we need a function first of this new editDishId. So basically what we're doing is, inside of the getter, it's a function returning a function, and that's why we can pass in a parameter. So to editDishId, we'll return this filter D ish, and this should be enter in like this, and then that should clean up the errors, although it's slightly off at a dish ID string.

Why is it not happy with this? So this is where an example of, unfortunate sometimes the errors aren't as helpful, but we kinda got ahead of ourselves thinking, well, we'll get DishById, not quite. The thing that's getting the dish is actually the function, and all we're actually returning is the function in this case.

Okay, let's now try this. So if we go inside of our editDishForm, we should be able to then say, const_targetDish is equal to, I have dish store yet, I don't have this dish store yet, const dishStore equals useDishStore. And then we can say, dishStore.getDishById, and then we need the props here.

So we say, props.dishId, and then we can log targetDish. But I think it's yelling at me because it's saying, hey, it might be undefined. So I'll just do this. If props.dishID is true, then do that, else, yes, this is gonna be a little bit weird. This is weird type wise already, but I wanna see if this works.

So here we go. So we have our Cancel here, we have our ghost peppers. Okay, so we can see here now we've actually fetched the actual object. So all we gotta do now here is, inside of here, once again, we have an error to do Fix types. But once again, we're trying to get to the finish line here.

So now that we actually have the dish, what we want to be able to do is actually update it. So in this particular case what I would say is, how do we do this? So we have Edit Name, dish name, v-model Dish.name. Okay, so what I actually could do instead is, we can just say the value is newDish.name, that's fine.

But then on input we will then say, or on keyup.enter, just like we did before, then we'll say, updateDish. So the way we'll do that is const updateDish is going to go ahead and it's just a normal function. And then we're gonna say, targetDish.name equals newDish.value.name. Can I do that?

Yeah, that's fine, I'll fix the types in a second, we just wanna see if this works. Okay, swap it on over. So then we'll say, Mystery Shrimp, create, wait, that one actually, that should trigger it. So now if I go back to dishes, it broke. Okay Edit Test, create dishes.

Nope, does not like it. UpdateDish, I didn't hit enter, silly me. Okay, that should do it now. So then we'll refresh. Add it here, Mystery Shrimp, Enter. Enter did something, and then if I go back to Dishes, I wanna go back, I know why, silly me. So I thought I was in routing, this requires an actual switch.

So similarly, we need to cancel an editDish basically. And I realized on the editDishForm for whatever reason, yeah. Okay, this is what I need to switch. So going back to the Dishes page, we'll go back to the dish card. And so when we cancel, wait, here we here.

Listen to cancelDish, cancel-new-dish. Then we'll say cancelDish, or cancelEdit. And so now we can do const cancelEdit equals a function where we then say the showForm.value equals that. So basically we're reverting it back to the thing. So to show that it works, we'll go ahead and edit, we'll click Cancel.

And it did not like it, Cancel cannot admit that I did not get declared, okay? So this is where view is trying to help us because I made up an event without actually declaring it. So cancel-edit-dish like this, that should do it. Okay, so refresh again, ghost peppers.

Mystery, or I should cancel first, it does not like it. What is not picking up?
>> I guess it's cancel-new-dish on the template.
>> Is that what it's saying on the template? Yes, I think you're right. So just scroll down here, yeah, wait, nope, wrong thing. Cancel-edit-dish, typing is fun.

[LAUGH] Let's do this. I refresh, Edit, Cancel, there we go. Now we're good. So now Mystery Shrimp, Enter, that should update it. It just overwrite it. But, okay, but that's the general gist of it, right? There's kind of a lot of moving pieces here. And so what I will make sure to do is that, I'll make sure that the end result is updated cuz there's clearly a lot of moving pieces.

But at a high level what we did see is that, you basically need to, we had to hop into the store, use getters to grab something out. And then what's tricky and most likely what's happening at this point is that, you basically need to make a copy of the reference before you go off and modify it.

I was trying to take a shortcut here to just edit it directly, but typically what you do want to do is, you wanna actually mode it like. Basically when you load it in, make a copy of it. That way you have a local state change within your component of what you're modifying.

And then when you submit the change, that will trigger an update event to the store that will then update the set item, that's the path you wanna follow. So once again, that solution will be published to the 11 finished branch. But otherwise, this is also a chance for you to just try and debug this out cuz this is honestly fairly common scenario too as far as CRUD operations and updating forms and existing data.

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