Lessons: 11Length: 1.5 hours

Next lesson playing in 5 seconds

Cancel
  • Overview
  • Transcript

3.3 Extending Components

There are many ways we can extend components. A useful way to add features to components is with the Decorator pattern. This allows us to provide extended, and sometimes more specialized, functionality to our components.

3.3 Extending Components

Our modal component is fairly genetic and I like generic components. And in fact, I would want to make this even more generic. Because in my mind, a generic component is something that can be used in a wide variety of circumstances. Like for example, a model is something that we can use to display a simple message. Or we can prompt the user to make a decision or we can ask the user for more input. I mean, there's a ton of reasons why we would want to use a modal. And the more generic a component is the more we can use it to fit those circumstances. But with flexibility comes complexity. And if we wanted to create a modal for the user to make a decision, like a confirmation modal, well, we would have to do several things. We would need a title. Though, something that would be a fairly simple question like for example, let's say that we want to ask the user if they really want to delete a resource. So we would use the title to be a simple question, like delete resource. And then the content of the modal would be something more specific, like are you sure you want to actually delete this specific resource. So for that we will just have you know, like a paragraph, are you sure you want to delete and then the specific information. But then we also need to at least two buttons, we need an okay, and a cancel. So that we can determine if the user wants to delete the resource. So, we would have to use the footer here to have our two buttons. And a confirmation modal is something that we would want to use throughout multiple parts of our application. So we would then be faced with a decision ourselves. Do we want to set up a generic modal several times in order to prompt the user to make a decision? Or do we want to make a more specific modal component? Something that essentially wraps around our generic component so that we can easily ask the user to make a decision. And that's what we are going to do in this lesson. We are going to create a confirmation modal. So let's create a new file. We'll call this ConfirmModal.vue. And as far as the code is concerned, let's use what we have in App, because what we essentially want to do is wrap around our generic modal. It's a lot like the decorator pattern. If you're not familiar with that pattern, it's very simple. You have an object, and you wrap that object with another object to provide extended functionality. That's practically all it is and so in this case, we are going to essentially do the same thing. We are going to use our modal, and we are going to add more specific functionality. Now, as far as our template is concerned, all we want is a modal so we'll get rid of everything else. And as far as the JavaScript is concerned, we don't need the name or the data and we don't need the style. So we're going to use that to start off with. And let's just run with this, let's start with the title. So unfortunately If we were going to consume this, in fact let's go ahead and change this, so that we have our confirm a modal. We would still want to set that up to bind to modal shown, and we would still want to listen for the hide event. Now as far as the backdrop is concerned, let's not do that. Because we could say that a confirmation model should have a static backdrop. Something that doesn't allow the user is dismiss the model if they click somewhere else on the body. So we could say show end and we could setup the and we would have a title. Our content and then we wouldn't need a footer. So the first question is how do we handle the title? We are trying to use the slot for our title in our generic component. But unfortunately, whenever we consume our confirm-modal, this template is not going to flow through to our generic modal. So instead, what we have to do inside of our ConfirmationModal is Essentially pass it onto our generic modal. So we're going to recreate that title slot, and then we will consume the title slot in our generic modal. So it's going to look like that. Now as far as the default content is concerned we will essentially do the same except that in this case, we're just gonna have our default slot. So whatever we have as our default content is gonna be used for our default slot which is going to flow on through to our generic modal's default slot. So that makes sense, and then as far as our footer is concerned, this is where we will have our two buttons. So let's start with the cancel button, and we're going to use the secondary class here. Now as far as dismissing the modal, we have been relying upon bootstrap to do that for us. If you set this data-dismiss attribute and set it to modal, then that will close the modal. And that's worked very well thus far and we'll just keep using that. If it came to the point that we need some more control over that, then we would probably want to avoid using the data-dismiss and do everything with JavaScript. But it's working fine, we're just gonna keep trucking on. And then the text will simply be Cancel. But then we need another button for the okay. And I'm gonna call this the Confirm button. It's the button that the user would click to say that yes, they want to do whatever it is that the modal is prompting them to do. So this would be our Confirm button. Lets use The primary class. The data-dismissed still needs to be there because whenever the user clicks on that button, it still needs to close the modal. And then for the text, let's have okay. Now one thing we do need to think about is how do we want the consuming component to know that the user confirmed the question. So in this case they clicked on the okay button. Well, one option would be to use v model. So that if the user clicked on the OK button, then the value would essentially be true because they confirm modal would have just one of two values, true or false. So if they clicked on the OK button, then it would be true. Otherwise if the modal closed, then it would be false and that would be one approach. But what I would want to use is a confirm event if the user clicks on the okay button or the confirm button. Well, then that will issue an event so that we could then execute some codes. So, let's say that we would have a method in our app component called delete resource. So let's go ahead and add that method just to have something there. And of course we need to do something in this method. So, let's alert and we will say resource deleted. Just so that we can see something without having to open up the console. So, with that in place, what we need to do then is handle or rather emit that confirm event. So whenever we click on the OK button, we will emit confirm. And that will make that work. Well, let's change the backdrop to static, because we do not want the modal to be dismissed by clicking on the body. The user needs to explicitly click on the X, or the cancel button, or hit the escape key to dismiss the modal. And that should be it. So let's go to the app. And let's make them necessary changes that we need. Like we need to change our import to confirm modal. And we also need to register confirm modal instead of modal. And let's see if this works. Well it doesn't. So let's look at the console, let's see what we get as far as errors are concerned. And you know what, let's just do a refresh to make sure that we have fresh errors. So we have a property method a model shown is not defined on the instance but referenced during render. And this is the confirmed modal, which makes sense because that's one thing we did not do. We are using the modal, and we are passing its show prop and we don't have this modal shown. Well we don't really need modal shown here. Instead we could have our own show prop so we essentially accept a prop called show. And we just pass it on so let's go ahead and add that. So that we have that show prompt but we still have an issue with this hide. Well, really we don't need to set anything here, we just want to essentially listen for the hide event on our generic model. And then, practically just resubmit that. So what we'll have is emit and then hide, and that's it. So after we save this, then we should see it working. Let's make sure that we don't get any errors. Looks like we don't. If we click on Our button to show the model, we see it. If we click on the OK button. Well then we see resource deleted. So that works. And if we click on Cancel, if we click on the X, we can see that everything works as it should. And of course, since we set the backdrop to static, we cannot dismiss the modal by clicking on the backdrop. We have to explicitly close it. So we now have a confirm modal. But I'm not please with it for a couple of reasons. First, the styling. All of the text for this modal is about deleting. And the two things I see here. First is the blue color of the confirmed button. You know to me deleting is dangerous. I would want something that represents danger here so I would like to be able to configure the model to have a different color button if we needed to. The second thing is the text. I would like to be able to change the text of our button so that. In this case, it would delete instead of OK, because to me that makes sure that the user knows that they are going to delete something. I mean, yeah, we're prompting them, but at least the button that actually executes it says delete, too. But then, I'm not really pleased with this, essentially, re-setting up the show prop and the hide event. And this is actually going to get worse, because in the next lesson we are going to create an even more specified confirm modal. One that uses our new confirmed modal as a basis. Which means that we are going to have to essentially do the same thing by passing on the confirm event, just like what we did with hide. So that's something else that I want to change, and we will do all of that in the next lesson.

Back to the top