
Lesson Description
The "Component Design Patterns Exercise" Lesson is part of the full, Intermediate Vue course featured in this preview video. Here's what you'd learn in this lesson:
Ben instructs students to create a BaseTextarea component by applying key concepts like component wrapping and prop usage. He also addresses naming conventions and best practices to prevent conflicts, along with troubleshooting script setup and TypeScript type inference issues.
Transcript from the "Component Design Patterns Exercise" Lesson
[00:00:00]
>> Ben Hong: I've talked for a little bit and now it's time for you to go ahead and get some practice in. So, what I'm gonna do is I'm gonna go ahead and push up the branch that I just did. That'll be 01-begin. And then I'll do a branch right now called 01 exercise.
[00:00:14]
So that'll basically pick up where we just left off, but that way you'll have kind of the Latest check out 01 branch exercise for later. And so the goal here for this particular exercise is you're going to be then. So text area is actually in this particular app, used a little bit more than text input, surprisingly.
[00:00:34]
And so I want you to go ahead and take what we've learned so far and to create a base text area component where we apply basically the things that we learned about as far as like wrapping the component in a vendor wrapper component. You're going to go ahead and make it transparent, pass its attributes, and just basically make it work within the app and then refactor it as you see fit.
[00:00:53]
And then for those of you, if that is too easy, feel free to go ahead and look at other things that you can refactor inside of the app regarding forms and whatnot. How did everyone do, did that work out okay? All right, well, if you had any trouble with it, no worries.
[00:01:14]
We're going to walk through it together. All right, so when it comes to refactoring this part, obviously first thing we're going to do is just kind of see where the text areas are being used. So, we can see that we have them using three areas. So I'm just going to pull from the task form modal to start.
[00:01:27]
And if we analyze this DOM element, we can see here that besides the text area itself, similarly to the import that we saw earlier, the input that we worked with earlier, we had a label here and we got a form control. So I think we have a good place to get started then.
[00:01:40]
So I'll go ahead and actually just copy this to start and then we're going to go ahead and create a new base text area component. And so some of you actually may have noticed that I'm prefacing all of these sort of wrapper components, especially when they're wrapping DOM elements with base.
[00:01:57]
You can also preface it with your company's two letters of your company's name or whatnot, but it's generally recommended to do so because you don't want to conflict directly with any sort of native DOM implementations. And so the general convention is that not to use single word component names just to avoid those sort of future collisions.
[00:02:16]
There's a couple of times review does it natively, but again, they're paying attention to the spec at a level that most of us probably aren't paying attention to. So it's just one of those things that you'll see that I do as a best practice to avoid that happening.
[00:02:28]
All right, so we got here, boom, we have this perfect. And then what we're going to do here is we're going to start by just defining the props for the basic things that we want to control very specifically for. So, we have things like the label require, true.
[00:02:48]
And then we're going to do the ID again and this time I'll remember that I required it, unlike last time. So we'll make sure to have that ID and label. Great. So, we're gonna replace both of these things with id. And then that did not work the way I wanted it to.
[00:03:04]
So there we go. Now we found those. We got the label here and then basically it looks like the main piece we need is. We don't need that. We don't need to. You know, honestly, I would like to make the placeholder something that is being sort of alerted to it is something that we find to be a good user experience for people.
[00:03:22]
So we'll make that something that's defined as well. And that way it's explicitly here in the component API. And then finally we just got to deal with this description part, which we've learned now we don't have to set all that model value emit stuff. All we got to do is say const.
[00:03:40]
Basically, in this case I can just say model value equals define model. And then just again, just a sprinkling of TypeScript here. The basically the greater than less than symbol allows you to pass in what type that you expect define model to be. So you can see here now, define model is a string.
[00:03:59]
And so now that we have that, we can go ahead and just bind it to model value. And then to make sure this works, now that everything is good. We're still missing one thing, actually. We need to go ahead and define options. We're going to go ahead and disable the inherent attributes or inherit adders and we're going to go ahead and V bind everything else directly to the text area, because that's the main thing we care about.
[00:04:29]
Then from here we can go ahead and jump on in and we can refactor this now to base text area so let me make sure this imported correctly. I don't think it did. It did, fantastic. There's our base text area. Although, yes, that looks right. Okay, so base text area is imported correctly.
[00:04:50]
Now we just need to go ahead and seal this off. Self closing. We have the id, we have the V model. We don't need the class, we don't need the rows. We have the placeholder. And it looks like this one is still erroring out because what did I forget?
[00:05:07]
I forgot the label. And this one we're just calling it description. So now that should take care of that. We don't need any of that boilerplate anymore. And there we go. And so, to make sure this works, obviously this we're currently in the task form model, so let's go ahead and run over to our app.
[00:05:25]
Let me make sure it's running. Looks like it's running. All right, so we have our tasks, our task modal here. There we go, deep dive into its features. This is my new update. Update. Task edit. There you go. And it saved and updated accordingly. So we'll just for the sake of completing the exercise fully, we're just going to quickly then just do essentially a search and replace.
[00:05:49]
So we'll do base text area again. I'll make sure the input is correct later. I think already with that highlight, it probably isn't disabled is good, Placeholder is good, class is good, id is good. But we do want that label for there. I usually like to put the dynamic stuff a little particularly V model a bit, little, little bit higher just to let developers know that's there.
[00:06:12]
And then we don't need any of this. So that takes care of that. And then this is the time entry form model. So where that is is you'll see that your task can also then basically track how much time has been added. And so, this is the time I spent on this component and then add.
[00:06:35]
And you can see here. There we go, we have our description still working great. And then finally we got one more which is looks like the weak form modal. So, this one we'll go ahead and let's drop the label here first. That's the one that seems to be erroring out the most.
[00:06:51]
Base text area. Delete all that stuff. Delete, delete, self closing. Delete div, don't need the rows, don't need the class save. And then I assume it imported correctly, but we'll check. Nope, did not this time. Did the type. Don't know why it does that. It seems to be like a 5050 thing with the auto import.
[00:07:13]
Yep, that one looks good too. So the week four model then on the other hand is when we go to our planner and we want to look at a week, this is where we can add the goals for the week. So this is my new goal update and then it's still here.
[00:07:28]
So we're good. Yes, we got a question.
>> Speaker 2: What is this being saved to, like the database?
>> Ben Hong: The database, yes. So, the way this app currently works is there is a back-end folder that basically. And there's a database .json, adb.json. The way this works is it's just a static file that's local, but combined with this awesome open source library called JSON Server, it stubs out a REST API that allows you to basically create endpoints to hit the shape of the DB JSON and then update it accordingly.
[00:08:03]
So it looks like that's good. And so I'm going to go ahead and make sure I commit this to the exercise. Well, let's see. Actually O1 exercise is where we started. So I'm going to check out now 01 solution and then we'll go ahead and add everything we just did.
[00:08:19]
Say refactor, create base text area component, And ref and place. That's fine actually, that should be good enough. Okay.
>> Speaker 3: So for some reason my ID and label are getting passed through as. Adders, not props.
>> Ben Hong: In your base text.
>> Speaker 3: I have defined props.
>> Ben Hong: Yeah. Okay, let's see this actually, this is something to.
[00:08:53]
>> Speaker 3: So I don't see like, I don't see the label printed on page where it should be. The id works because it's an adder and it's kind of splatted across the rest of the adders. Works for you.
>> Ben Hong: So in case anyone is not seeing their attributes show up.
[00:09:09]
So. So we see here that the description here is showing up. We did a little debugging earlier and so if you're not using script setup right here and then I think. I think I probably broke it, hold up. Do, no, that should be fine, run dev. Go, define off well.
[00:09:33]
That's how you go. There you go. Remember I said the auto import. That's funny. Let me do this real quick, define props. I'll explain this to everyone. So, you're aware of this, okay? There we go. Okay, so you'll notice here I just recreated the bug. That label has magically disappeared, right?
[00:09:58]
It looks like everything is fine because after all we've imported all of our. What seems like our helpers and so it should work. This is where I think it's a little bit of a gotcha with the Composition API and the new script setup authoring format is that there's actually a.
[00:10:14]
Let's call it a magic engine running underneath that does a bunch of stuff because we have this setup attribute added on. So even though you theoretically imported these helper methods up here, the compiler isn't there to optimize for those things and therefore is basically not not being caught.
[00:10:31]
And so for those wondering, you might have noticed that I did not actually explicitly import those. And that's just because when you're using script setup, these macros like define options, define props, define model, they're just assumed that you're only using it in the script setup context and therefore you don't need to.
[00:10:47]
However, just to be clear, I think I mentioned this just before I walked over here that it is totally fine if you want to be explicit for your developers where these things are coming from. And this is not assumed knowledge. It's totally fine to leave it up here as well but just know that it's not required from an import perspective.
[00:11:03]
>> Speaker 4: So I had the kind of opposite problem where I had left the label prop off of my base text area and it just loaded up without a label. So the requirement of the prop didn't trigger anything, any errors.
>> Ben Hong: Interesting. So what you're saying, just to make sure I understand, is that you left off the prop definition.
[00:11:28]
>> Speaker 4: Nope, the prop definition was there with the required, true. When I implemented using the component I didn't include the label as part of.
>> Ben Hong: Like the props definition.
>> Speaker 4: The props that are passed into it.
>> Ben Hong: And then it was fine.
>> Speaker 4: And it seemed to be fine.
[00:11:44]
It just didn't render the. It just essentially rendered nothing for the.
>> Speaker 5: If you didn't have script setup, it would do that because it wouldn't know that it's required because it doesn't actually use it as a problem.
>> Speaker 4: Yeah, but I've got script setup, I think.
>> Ben Hong: No, I think, let's just try to recreate this real quick.
[00:12:01]
So I'm in the weak form modal. You were mentioning that if I delete label like this, right?
>> Speaker 4: Yep.
>> Ben Hong: Save it.
>> Speaker 4: It did not throw the error for me.
>> Ben Hong: Refresh, edit.
>> Speaker 4: It did this.
>> Ben Hong: So yeah, it just showed up. This honestly might just be like the TypeScript server might need to be restarted.
[00:12:19]
That is something that people actually. I guess this is actually worth calling out. So in the event you ever noticing your type inferences are not really working as expected, there is this ability to this one. So in your VS code, the way I do it is command shift P Or if you do command P, basically you're opening your command line and.
[00:12:41]
And then again, for those who are new, if you have this greater than symbol, this will basically. Rather than just like, for example, if I don't have that and I just type restart, it'll actually look at files inside of my directory. The greater than basically forces it into command mode, essentially.
[00:12:58]
And so if you'll notice that if I do a restart, then you'll see view, restart, view, and Typescript servers. Sometimes that's just what you need to do in order to get everything working. And so, if it's ever looking funky, like you're like, I definitely defined that correctly. Why is it so yelling at me?
[00:13:11]
Yeah, try this first. I use this quite often. Great questions. Thanks for calling those things out. But yeah, this is also what's interesting about different type checking is that we technically have the required true as a prop, but because that's a runtime check, it won't actually stop the actual build output.
[00:13:32]
So for those who are wondering, and that's one of the reasons why I think we've seen a lot more code bases opt into the Typescript, is because you theoretically want your build to break or basically to stop you in the event you have things that are clearly missing that you've said is required.
[00:13:48]
Little things like that. But again, this is not a typescript course. And so, we're just sprinkling it in here and there. Just start getting people familiar with it. So there we have that now. Whoops, okay, did I do anything else? Yeah, that was just testing and okay, great.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops