Lessons: 11Length: 1.5 hours

Next lesson playing in 5 seconds

Cancel
  • Overview
  • Transcript

4.2 Using the `render()` Method

Sometimes, it makes sense to write a component that renders content without a template. In this lesson, we'll revisit our first component (the form field) and render it using the render() method.

4.2 Using the `render()` Method

We will build the vast majority of our components using a template. I mean, just look at the components in this course, everything that we've done uses a template. And chances are the majority of your components in your applications use templates as well. I know mine certainly do, but there are sometimes when it doesn't make a whole lot of sense to use a template, and instead you would want to render your component using nothing but the render method. And that's what we are going to do in this lesson. Now, you might ask yourself, why? Why would I want to render a component using JavaScript, as opposed to using a template? Well, there are sometimes when you need to drastically change the way that your component is rendered, and sometimes that might actually be easier to do that with JavaScript than with using a template. And as you will see in the next lesson, there are sometimes when using the render method is actually very useful. But we will get to that in the next lesson. In this lesson, what I want to do is rewrite our FormField component so that instead of just using an input element for our form control, that we could also take a textarea into account. So we could pass in textarea as the type, or text, or email, and so and so forth. And if it's textarea, then we will output an actual textarea, otherwise it's going to be an input. And you can make the argument that, well, we could easily do that with a template, and I understand that. However, we need an example and this is as good as we can get. So we are going to leave the templates here for our FormField component, just so we have something to go by. And then we will eventually take out the template, and see if our render method is going to work. So the render method actually accepts an argument called createElement. This is a function that we can use to, as its name implies, create an element. But really, what we are doing is creating an object called a VNode, which is what Vue uses to render our components into HTML in the browser. And the render method needs to return a VNode, so what we're going to do is simply return a call to createElement. Now, in this case we are going to pass three arguments to the createElement function. The first is the tag name, so we are starting with our div element, so the first argument is simply going to be div. The second argument is an object that contains a lot of information about the element that we want to create. It could be the attributes or the styling information, either through the style attribute or through the class attributes, it could be props. I mean, there's a wide variety of options that we have at our disposal here, but all that we really need to do is set this class of form-group. Now, we can actually do that in two ways, but since we have just a single attribute that we need to set up we're going to simply say class as the property. And then the value is going to be the the class, form-group. And then we have the third argument that we are going to pass, and this would be the children inside of this div element. So this is going to be an array, because we have multiple children. We have a label, and then we have our form-control. So let's have an array, and the first child is our label. So we're going to call createElement once again and our first argument is going to be label. Now, as far as our label element is concerned, we don't have any attributes. We have nothing for this element except the text inside of it, so we are just going to pass two arguments here. And the second argument is going to be the text that we want inside of this, and we have that through our label prop. So we will simply say, this.label. So it's important to note the distinction between these two versions of createElement. If we are passing two arguments, the first is the tag name, the second is the contents of that element. If we pass in three arguments, the first is the tag name, the second is an object that contains a variety of information about that element, and then the third is the children. So let's move on to our next element, which is our actual form-control. So this is where we are going to see some discrepancy. So what I want to do, then, is have a method that we could use to build the appropriate elements. So let's call this buildFormControl, we will pass in the createElement function because we still need that. And that's going to be our render method. So pretty straightforward, as far as this is concerned. Of course, we haven't implemented this buildFormControl, but we will get to that right now. So let's add our methods, and buildFormControl, we are receiving that createElement function. Now, before we call createElement, let's build an object that's going to contain all of the stuff that our element needs. Because there's going to be a difference between the stuff for an input element and the stuff for a textarea. There will, of course, be some similarities, but there will be some differences. So we're going to build an object, let's just call it options, and let's start with our CSS class. Now, up here, where we created our first div element, we just specified the class property and then gave it a string value representative of the CSS class that we wanted for that element. In this case, I'm going to use different syntax. Now, I'm only doing this to show you that this syntax exists. For our particular case it's really not going to give us any benefits, but if you needed to reactively toggle a class this is the approach that you would need to take. So you have class, but instead of just a string value it's an object. And then the properties are the CSS class names that you want for that element, so in this case it'll be form-control. And then the value would be a boolean value to determine whether or not that class is applied to the element. So as I mentioned, if you needed to reactively toggle a class this is how you would do that programmatically. Of course, instead of just hardcoding it to true, you would bind it to whatever prop or data property. But in our case, it's simply true. And of course, you would just simply add as many classes as you needed for your element. So we have a class, the next thing that we are going to do is set up the InputEventListener, which is very similar. We have a property called on, which is an object. And then the names of the properties for this object is the name of the event that we went to listen for. So we want to listen for the input event, and the handler is of course a function, and we are going to emit the input event, and then we need to pass in the new value of our form-control. And we will do that with e.target.value. So if we had any other events we would list them at the handler, and there we would go. Now, as far as our textarea is concerned, that's all we need. We don't need a type attribute, or anything like that. So let's go ahead and let's check the type of our component. So if it is set to textarea, then we are essentially done. We will return createElement, our tag name will be textarea, and then we will pass in our form-control options. And then for the third argument we have the actual value for our form-control, and that's it. Now, if we have an input element, we need to do one other thing, actually two things. We need to set the type attribute and we also need to set the value attribute. So we are going to build upon our options object. It has a property called attributes, or attrs for short, attributes, and then we simply set up the attributes that we want for this element. So the first is going to be value, which is of course the value, and then we have the type which is from our props. And then, we will simply return createElement. In this case, our tag name is input. We will pass in options for the form control information, and then that's it. Because the value is already a part of our options, so we're done as far as that is concerned. So let's get rid of the template and let's go back to App.vue because we want to, first of all, import this. Let's leave list here. In fact, I'm going to leave everything here, because we will be revisiting that in some way shape or form in the next lesson. We'll leave the data, that's not that big of a deal. But we do want to import the login, and I don't remember what that's called. So let's look, LoginForm, duh. [LAUGH] And then we will simply have that in our templates. We do need to register the Login component, and then we should see our LoginForm. Now, let's add a textarea to it. So we are going to need to open up our LoginForm, and let's just copy what we have for the email, and let's use that as a basis here. So as far as the label is concerned, let's just have a Message, which doesn't make a whole lot of sense, but okay. And the type will be textarea, the v-model, let's sets to message. And since we don't have that, let's do set message equal to an empty string, and that should be that. So if we save this, we now have our textarea, but let's inspect it. And let's see that the markup is what it should be. So we have a textarea, the class is form-control. Let's do this, let's start typing something so that we can see that added to our textarea data, and we do. Let's also inspect it through the View inspector. Let's go down to login, we now have a message, we can see that the value is what we typed into it. If we dive on down to our FormField, we are going to see that we have a label, we have the type for textarea, and we have the value as well. So as we, of course, update the value of the textarea, the value prop and the message prop is updated. So we have successfully recreated the FormField, we've made it a little more robust in that we can finally render the appropriate control based upon the type that is supplied. But you might be thinking, well, what's the relationship between this and especially scope slots, since we talked about that in the previous lesson? Well, you will find out [LAUGH] in the next lesson

Back to the top