Initial Project Setup
Hey, what's happening gang? Welcome to your 27th of Vue.js tutorial. And in this video, I want us to talk about slots.
Okay, so I've stripped out a lot of the code from previous tutorials and I've just got this root component right here, app.vue, with an empty template. And I've also imported another component called formhelper from the components folder, formhelper.view.
And that's this thing right here. Don't worry about the name of this file for now. I'll explain that later. And this just has a H1 in the template. So nothing else going on in this component. But what we are going to do is register that component right here saying the name of this component that we're going to use in the tag is form-helper. And it's this thing right here we've just imported. Okay. So I just want to nest this component form-helper in this root component now. So form-helper.
And let's just make sure that works. If I view in a browser, we can see 'I am the form helper' which is in this form-helper component. So it has successfully nested.
Passing HTML with a Single Slot
Okay, cool. So we've seen in previous tutorials that we can pass data down to these child components using props, right? We could say something like v-bind and then the title is equal to something that we defined down here in the data. Right? Well, what if we wanted to pass something a bit more complex such as a HTML template? So, we want to pass some kind of HTML down to the child component and then output that HTML in this child component somewhere. Well, we can do that not using props, although we could if we pass a HTML string in here, but probably not the best idea. We can pass down a HTML template using slots.
And this is pretty similar to something known as transclusion in Angular. So if you've used that before then this is going to be pretty simple to understand. But anyway we can pass HTML down using slots. And the way we do that is twofold. First of all we define within these tags, within the component tags what HTML we want to pass down.
Using Multiple Named Slots
So say for example we want to pass down a very simple HTML template with a H2 saying 'I am the slot title' and also a paragraph tag. And we'll say, 'I am the paragraph text for the slot.' Okay, whatever. And if we save this now, do you think that this is going to be output within this component? Right here somewhere. Well, let's have a look in a browser. No, it's not anywhere. And that's because we've not said where we want this slot to appear within this component. All right.
So, we've placed it within the component right here where we've nested it. But we've not said within that component where we want to output that HTML. And to do that, we need to use the slot tag. So say for example, we want to output it underneath this H1. We can just place a slot tag beneath that H1. Save that. And then it's going to output whatever we put here where this slot tag is. Okay. So let's view this now. And we can see it right there. So just to test, let's place this above the H1 as well. Make sure it works. And yep, now it goes above the H1. Cool.
So, what if we want to output, say, for example, this above the H1, but this below the H1. How can we do that? Well, we can do it using two different slots. So, we could have a slot above, but also a slot below. Now, if we save this currently, then both of these things are just going to output twice because Vue.js doesn't know which to place in slot one and which to place in slot two. So it just places both of the tags in both. So we need a way to say to Vue.js, well I want the H2 here and we want the paragraph text here. And we can do that by naming our slots. So if I give this slot a name, and I can do that by saying slot is equal to whatever name I want to give it. And we'll call this the title. And then I'll come down here and give this one a name as well by saying slot is equal to text. Then save that. We can now come over here and say okay we want the title slot there and the text slot here. And the way we do that is by giving this an attribute called name. So the slot name is equal to title in this instance and the slot name over here is going to be equal to the text. Okay.
So let's save that and see if it works. Okay. Okay. And if I refresh, then you can see the slot title goes at the top and the slot text goes at the bottom. Cool. So that is how we have multiple slots. Okay. So we can output different content we place here in different places in this tag right here. Okay. Using different name slots.
Slot Data Scope and Styling
Okay. So if we want to style these slots, what can we do? Well, we can just add styles as normal down here. So I could say H1, and we'll give it a color of red. Save that. Cool. So we can add styles right here. Now what if I want to add some kind of method or dynamic data? So could I instead say for example of this output some kind of dynamic title? Well, yeah, I can do that. But this time we don't do it in this component on the data right here. We do it in the component where we kind of initialize this slot title. Okay. So we can add the title property right there and say 'I am a dynamic slot title'. Save that. And we can see update right there. Okay.
Now if this was to be defined on the component which is nested, where we actually see the slot, then let's see if this works. Save it. And now we're not getting anything whatsoever. So even though this HTML is being passed down into this component, the dynamic data we output must be defined in this component right here. Okay, where we use these kind of template tags. So let's place that there again and save it. And again, we get it working.
Okay, so these are just some simple examples. And you might be thinking, well, this is pointless. Okay, so why not just place this stuff right here instead of between these two tags? Why not just place it in here and save yourself all the work of naming slots? Well, we could do that, but I'm going to show you an example now where we can use slots, which is beneficial.
So imagine this scenario. We create a website with many different forms on it and we want to give the front-end developer a way to easily create these forms based on an existing template. Okay. So, we want the front-end developer to be able to specify some form fields, a form header, maybe what happens when they click on submit such as the form controls, etc. But we want the general outline and the structure of these forms to be the same on each one of them. Okay? Well, we could use this idea of slots to do that. So, this is all going to become clear as we approach the end of this tutorial.
For now, what we're going to do is create some kind of template for this form in this component, this form helper component. Right? So, the idea is that a developer would use this component, then add slots into it to pass their own data into it, and that's going to create a form for them on a website.
So, let's go ahead and start padding out this form. So let's say we have a H1 at the top of the form which says 'please fill out our form.' Okay. Now this is going to be on the head of every form page. Then we're going to have a form tag and inside here we'll have a few different sections. So we'll have a section for the form header. So we'll say div id equals form-header. And then we'll have a section below that for the form fields. So we'll say div id equals form-fields. And then below this we'll have another section which is going to be for the form controls. So we'll say div id equals form-controls.
And then at the bottom of that we'll maybe have some useful links or something like that. So we'll say div id equals useful-links, you know, things like about us or something like that. Anything to do with forms. So we'll do a ul inside here in fact. And this is just going to be a little list of links. So li tag an a tag with a href. Doesn't really matter where the href is going at the minute. This is just a dummy link. So say link one. I'm just going to copy this dude now and paste it down below a few times.
Okay. So, now we've got this general kind of structure for our form. Okay. And basically what we want to do now is be able to pass in things like a custom header, some custom form fields, a custom form control, anything like that into this form helper. And tada, we can do that using slots.
Okay. So say for example, we could have a slot here. We could have a slot with a name equal to form-header. Okay, doesn't have to be the same as this ID, just happens to be. So now we can inject content here from the parent component and it's going to be injected right here for the form header. So we can have a custom header in this form. We could do the same thing for this. So let's just copy that and paste it down below and change this to form-fields.
We'll do another one for the form controls and change this as well to form-controls. So now we have kind of three editable regions on this component, on this form helper, and we can pass into these editable regions from the root component. Okay. So when a developer now is creating a form, they don't need to start creating a new form from scratch. All they need to do is call the form helper right here and then pass in the data, the custom template that they want to appear in the different sections of this component. So they could pass in if they wanted to a form header, some form fields, and some form controls. Okay? And the structure of the form is going to remain the same in each case.
So let's pass some stuff in. So the first thing I want to pass in is a slot for the form header. So I'll say div. And remember we need to say slot equals and then the name must match up to this thing right here, form-header, because this is where it's going to go. So we'll copy that and paste it in there. And the form header is going to have inside of it a H3, and it's going to include all of this stuff. So when the slot goes in, it's going to include everything that's nested within this slot as well. So the H3 can be some kind of title, some custom title. So this is the title of the form and we could have a paragraph underneath it if we wanted to, like information about the form.
And then what we'll do is another slot now for the form fields. So, we'll say div slot equals form-fields. And then inside here, we could pass in any number of form fields such as inputs or text areas, that kind of thing. I'm just going to do a couple of inputs. And there's going to be an input type of text. And this is going to be for the username or something like that. So I'll say placeholder equals name and this is going to be required. Okay. And then what I'll do is another one down below and this is going to be for the password. So I'll say type equals password and placeholder is password and that's required as well.
Okay. So now we have these two sections, these two different slots entering into our form help component in these two areas. So now let's just do the form controls. And this is just going to be a button. We want to pass in a button with a function attached to it so that when user clicks on this button then something happens when we submit the form. So we can add that in as well. We'll do a div here. We'll do a div right here with a slot equal to form-controls. And then inside here, we're just going to do a button. And this is going to have a click event attached to it. So we'll say v-on:click is equal to handleSubmit. And then we'll say submit.
Okay. So now we've passed all of these different things into this form helper. We've not had to write out all that form, just the different editable regions if you like. And then this form helper is going to take all of those editable regions, combine it together in this form with the structure already laid out, any styles that we need to add here as well, and it's going to output that for us. Just going to get rid of this style right here and save it. And I'll save this one as well. Let's have a look in a browser so far. And now we can see this form is made.
Styling the Component and Conclusion
Now it doesn't look great at the minute, but we could also add some styles into this form helper component as well, so that no matter which form we create using this form helper, they're all going to look the same. Okay, so we'll add these styles right down here. I'm just going to copy and paste these from my GitHub repository. You can get them from lesson 27. The link is down below. So I'm just going to paste these right in there. Save it. And let's view this now.
Cool. So now, every time we'd make a form on our website, it would look something like this. And yeah, I know the form styles are pretty crappy as well. I just added some basic ones here just to kind of pad it out a little bit. But the idea is we could have our own custom styles in this form helper. And then every time we create a new form, this is all we need to do. We don't need to worry about styles. We don't need to worry about the structure of creating the whole different form. All we need to do is worry about these different slots, these different editable regions we're passing in to the form helper.