Build a Fullstack App with Vanilla JS and Go

Movie Details Component

Maximiliano Firtman
Independent Consultant
Build a Fullstack App with Vanilla JS and Go

Lesson Description

The "Movie Details Component" Lesson is part of the full, Build a Fullstack App with Vanilla JS and Go course featured in this preview video. Here's what you'd learn in this lesson:

Maximiliano explains the process of creating a web component for a movie details page, including registering the component, loading CSS files, using Shadow DOM for styling, fetching movie data from an API, error handling for non-existent movie IDs, and populating HTML content dynamically.

Preview
Close

Transcript from the "Movie Details Component" Lesson

[00:00:00]
>> Maximiliano Firtman: So what's the next step? The next step is trying to render the details of a movie, okay? So right now, we are rendering the home page. Now I wanna render the details of a movie. So for example, the whole idea, my whole idea, is that if I click in one movie, if I click in Minions, I wanna get into the details of Minions.

[00:00:22]
So I need to render another page that is gonna be movie details, okay? And we have already said that for every page, what they're going to do is create a web component. So the next step is create another web component for movie details. So we can start with the HTML, or we can start with the JavaScript, the order doesn't matter, okay?

[00:00:48]
The thing is that we will also need some HTML as well. In the readme, we are now on D5, you have both there. For example, I may wanna just copy the HTML, because it's just a couple of tags, and I will code the JavaScript bar. So this is a new template, so I'm going to paste from D5 the HTML.

[00:01:17]
So I'm going to now my index real html, and I do have a section that I created for templates. So far, I only have the template home. I may wanna get rid of these spaces just to have a cleaner HTML, it's not mandatory. And then I have the template home, and I'm going to paste now template-movie-details.

[00:01:41]
Okay, so let's analyze the code here. First, as you can see, I'm already using animated loading, okay? So I'm already using here the other component that we have already created. So it has an article for the movie. The article element is semantic HTML. h2, h3, then a header, the header has an image for the poster.

[00:02:07]
A youtube-embed, okay, and say, what's that? Okay, we'll see. Is that HTML? No, and how do I know this is not really from an HTML spec? Because there is dash. Every time you see a dash or hyphen in an HTML tag, you know it's a custom element. Do we have it?

[00:02:29]
Not yet. Okay, what would happen? Would we get an error from the browser? No, not really. When the browser finds an unknown element, it just ignores it, and it just applies the standard HTML unknown element. Actually, you can even put some text inside, like YouTube, whatever, and the browser will render it.

[00:02:56]
Okay, and that's something that I'm not sure if you have seen, it's a history lesson, so it's not really important. But I'm not sure if you know that there is a noscript tag. Have you seen that one? So we have the script and the noscript. I say, why do we have a noscript?

[00:03:15]
Does anyone know? I'm not sure if you have seen it, because I haven't seen it, or haven't implemented in probably 20 years. But it has to do with that, with this idea. In the 90s, there were a couple of browsers without JavaScript support, okay? So if you had something in JavaScript here, it's not gonna work.

[00:03:35]
So when the script tab was created, they also created the noscript. Here, you will add a message for browsers not supporting the script, such as you need to update your browser, bro, right? So that means that browsers with support of the script tag will just ignore that text.

[00:04:01]
And browsers that are not understanding the script tag will ignore the script tag, and they will also ignore the noscript, but not the content. So they will render this. In fact, we can use the same technique here to put here, like, YouTube loading or something here, or even we can add an animated loading.

[00:04:21]
So if youtube-embed is not being recognized, well, at least we have a fallback content. So you use that for fallback content.
>> Speaker 2: So does it replace it with a div or something, or there's just no element at all?
>> Maximiliano Firtman: So no, there is an element, so you will see the element in the DOM is there?

[00:04:39]
But it's more similar to a span than to a div, so it's not block-based by default like a div. But actually, you can apply CSS to it and say display block, even if the tag does not exist, okay? It treats as a placeholder. Then we have a section for some actions for metadata like the release year that we will add later, some two buttons, and then the cast, and blah, blah, blah.

[00:05:08]
So nothing really important, okay? So that's actually the template. And of course, we will use the web component to actually fill the gaps here. So the next step is to create the web component, so I'm going to create a new file. The new file will be, in this case, MovieDetailsPage.js.

[00:05:31]
And it's gonna be an HTML element, so I'm going to say class MovieDetailsPage extends from HTMLElement. Of course, we also need to register this, because if not, we won't be able to use it. So the last part will be, again, customElements.define movie-details-page, we can have more than one dash, and the name of the class.

[00:06:02]
Yeah, we have a question there.
>> Speaker 3: Can you load a CSS file from a web component?
>> Maximiliano Firtman: Yes, you can load a CSS file from a web component. How you're going to do that, there are different ways. One way is, inside the template, you can add a link.

[00:06:20]
You can also add a style. Or you can, inside the template, so then remember, the template is gonna be cloned, and then when we clone that, we will inject that clone in the DOM. That style, by default, will be applied to the whole page, not just your web component.

[00:06:38]
If you want that CSS to apply only to the web component, you need to apply Shadow DOM, okay? We don't need it for this particular example, but Shadow DOM can be defined in JavaScript or in CSS. From CSS, it's called declarative Shadow DOM. And you define Shadow DOM from here, and Shadow DOM mode, and you say, actually, Shadow Mode, not Shadow DOM.

[00:07:09]
And you say, open or close? What is that? If you let CSS and JavaScript from the outside to read the inside, that's open. Or if you wanna be a black box, and then you don't let JavaScript or CSS to get into your web component, and that's a close Shadow DOM, okay?

[00:07:31]
So yes, you can apply CSS, and you need to define or decide if you want it to be a Shadow DOM or not, okay? So what's the difference here, compared with the other solutions, is that I actually need a movie, because I will render a movie. So I will start with no movie at all, and someone needs to send me a movie so I can render the movie, okay?

[00:07:59]
That's It's kind of the idea. So who is going to send that? We will see later, but we can use connected callback.
>> Maximiliano Firtman: And we can try to get the ID from different places. Okay, there are many see many places where we can get this. For example, we could have a property call ID, okay?

[00:08:30]
We can get it from data set, okay, there are many ways to do that. We will probably refactor this in a minute. It when we create a router, okay. So for now, let's say we will get an ID. In fact, so far, we can even fake the ID.

[00:08:47]
Let's say the movie 14, okay, so we will always render that one, and then we'll see where the ID will will come from, okay. And then we need to render actually. We need to connect all the details, because rendering is typically a pattern. It's a pattern that I use.

[00:09:08]
Not every developer is using this pattern. The pattern is creating a render method. I will explain why it's a good idea to create a new method. This data connected web component needs to go to a server. Because we need to go to a server, we will probably call the API, right?

[00:09:28]
For example, the API will actually try to get the movie. So I need to call the API first. I need to import the API now we know that we need to add Js, careful with that. The API, we have a get movie by ID. So if I do have the ID, for example, this dot movie is my ID, this is returning a promise, so I need to await for the promise, right?

[00:10:00]
So if I need, if I other way, that means that I need to add async to my function. So what's the problem with this? If I do this in connected callback, then I will need to add async to the connected callback. And if you do that, you have a problem, because that's not the thing Signature of the superclass, and then you're not that it's not going to work.

[00:10:27]
So connected callback is not an asynchronous function. So of course, this function can call an asynchronous function if you want to do it here, there are ways. You can wrap this, in a function, an async function, put something like this and then execute this little function like that.

[00:10:50]
But it's kind of, yeah, I'm not sure I want to do that. So it's much better to just call render okay, or any other method and that will solve the trick. Okay, does it make sense? But that's why we try to keep connected callback as small as possible, and also without changing signature.

[00:11:10]
We you cannot receive arguments, for example. You can add that because, remember, arguments in JavaScript actually does not exist. They are kind of a ghost. So I can add arguments here, but no one is going to send me arguments ever. I won't get any values ever because actually the browser is executing connective callback and I will never get something from those arguments.

[00:11:36]
Actually, what I want to change is the movie, not the ID. So we can say this movie is movie 14. Of course, we will change that 14 later. That's to do here, and I will get the movie. So actually, what something that I can do here is there are many things that I can do.

[00:11:56]
Maybe I can say this is, let's say we have an ID start as null. So let's say the id as 14 and we use the movie for the actual movie, okay? So that's probably gonna be better. So we keep the movie with all the metadata from the movie there.

[00:12:14]
Remember, get movie by id. It's just, fetching movies/id. So if you want to see how it looks like API movies, 14, and this is what we're going to get from JavaScript. Okay, 14 is many in black, three and, yeah, title, Thailand, genre. And then we have overview the keywords, the casting.

[00:12:40]
Okay, Will Smith with the URL of Will Smith as well. So we need to just get that JSON, parse it, and populate, dynamically render our HTML with that, okay? Does it make sense? So,
>> Maximiliano Firtman: Once we get the movie, we could also think of what happens if I can get the movie, like if I'm using an ID that doesn't exist.

[00:13:10]
So the server is actually giving me that text but it's not just the text. If you look at the network tab, and look for all the server is giving me, sorry. Put this out.
>> Maximiliano Firtman: It's giving me a 404, because that movie does not exist. So we are using, in this case, the HD.

[00:13:40]
Status codes to actually send a message to the client. So, we should do something not rendering the content, okay? So, we will solve that problem as well, because in every real world project, you need to do error management. In every layer, okay? In every layer, Server side, we have a lot of error management.

[00:14:02]
But client side so far, we don't have a lot and this is one place, so something quickly that I can do is I can do a try catch. So if for any reason I couldn't get the movie. It can be any reason actually. I need to do something, so alert the user.

[00:14:19]
And we will do that, okay? And we'll see how to alert the user, yeah, I can put an alert, a pretty old fashioned alert, like movie does not exist. But that alert is pretty bad, okay, it's also synchronous, so it's a really bad idea. So we will change that, okay?

[00:14:40]
So we will replace that alert in a few minutes. Then if we get the movie, also we can say return, so we don't continue working with this. I need to get the template, document, getElementbyId, I will do this one more time manually, and probably the rest is just the same for the rest of the components.

[00:15:05]
Okay, I need the template. The ID is template, movie details, and remember, this is going to the HTML, finding the template. So we can actually use a template and then I need the content. It's template.content.cloneNode(true). The true has to do with getting with a deep search. So, if that template has other web components, it will also create an those web, and clone those web components.

[00:15:39]
And then, I will AppendChild of that content.
>> Maximiliano Firtman: So that means that now the template has been created. So we have an instance of that template in memory, and now it's in the dome. Here is in memory And here is in the go, okay? So the next step is I need to start setting all the data, I will just go two or three and then the rest we'll be copying from the material because it's just the same.

[00:16:13]
We don't wanna waste time on that. So for example, we get the h2 will be, so I'm talking about the template, remember. This is a template. The h2 we have the title of the movie. The h3 we have the tagline, that is something from coming from the data source.

[00:16:31]
So we take the h2 and then we change the textContent. For example, from movie title, and something similar for the h3 with the tagline. I have a question for you, do you know the difference between text content and innerHTML? This is vanilla JavaScript concept.
>> Speaker 4: InnerHTML accepts HTML attributes.

[00:17:03]
>> Maximiliano Firtman: Yeah, so innerHTML will accept HTML elements and attributes and they will be passed as that. And it's actually a little unsafe, because if someone is sending in the tagline, JavaScript, for example, you will also be injecting JavaScript. So when you use innerHTML, you're opening the door for cross-site scripting, okay?

[00:17:26]
So that's unsafe. There is a safer way to also inject HTML, but we don't need HTML, you need to use textContent always. It's faster and also it's safer. So if someone is hijacking your database and injecting JavaScript code, when you are trying to insert that, you will actually see the code and the code is not going to be executed, okay?

[00:17:51]
So that's the difference, okay? Makes sense? So, let's see if something appears now. Actually, to make this work, there are a couple of things that I can do. I can go to the API, actually to app.js. Right now we are appending a new homepage. Maybe we can also append a new details page, a movie details page.

[00:18:16]
I will say, MovieDetails page. But if I search for MovieDetails page, VS Code is not really suggesting me the class. And you can say, well, maybe VS Code is not working, okay? But maybe something else. So if you go to MovieDetails page, it's a class, okay? And you may be thinking, but it's capital M, so it should be public, but let's go, okay?

[00:18:43]
We are in JavaScript here. Actually, to make it work from the outside, I need to export this. You need to explicitly add the export, a default export or a normal export, because it's an ECMAScript module. So now if you try to create that, it will appear. And here we can prove something that I mentioned before.

[00:19:08]
If I press Return here, look at the auto import that VS Code will add. It will add me the right one, even with .js, why? Because there are others in the same project with .js so it recognizes that as the pattern for this file. The problem is the first one only.

[00:19:30]
>> Speaker 5: Why didn't we need to export the animated loading component?
>> Maximiliano Firtman: Just in case you wanna use it from JavaScript. By the way, that's a good question, actually. So, actually, we are exporting this web component in two different ways. One is the export, and the other one is customElements.defined.

[00:19:52]
What happens if I don't define this?
>> Speaker 5: It doesn't get registered.
>> Maximiliano Firtman: It doesn't get registered, but actually, I do have the class. So if I create the element from JavaScript, and you check the element from JavaScript, it may work. But it's not gonna work if I use the tag in HTML.

[00:20:14]
So the export is like a way to expose your web component to JavaScript, and the custom elements defined is a way to expose the same web component, but for the HTML, does it make sense?
>> Speaker 5: So utilities can be done, I guess components created through JavaScript and actual elements that you may need to render just I guess the way that you make them available for the user.

[00:20:43]
Say, like some of them are gonna be created through pure JavaScript, and you can just call them from other components, and the other ones could be your base.
>> Maximiliano Firtman: Yeah, that's right.
>> Speaker 3: You need to call this dot render inside connected call.
>> Maximiliano Firtman: Yeah, that's right. Because render, remember, is not part of the lifecycle of a web component, so I need to call it explicitly from here.

[00:21:04]
Also, you may wanna call it on every time an attribute is changing. Maybe, okay? Maybe, okay, it depends on the web component, but have in mind that this is only connected callback and it's not going to rerender automatically when an attribute changes. So it's not like reacted when a prop is changing, render is executing again.

[00:21:24]
No, not automatically, okay, yep?
>> Speaker 3: Could you use template strings in here? And what's the difference between using the template and?
>> Maximiliano Firtman: Yeah, so a template string will be instead of using the HTML template, I could just say something like this, inner HTML, and then open template string and start writing my HTML like this.

[00:21:52]
Here, we pull the title, so there are differences. So first, it's a matter of taste and a decision on the design pattern you are using in your page. This one is less safe for this whole idea that we are using in HTML. Anyway, there is a new way that today is kind of compatible with every browser to add HTML that is safer.

[00:22:17]
Like it's not going to execute JavaScript and that sort of things. Also, this may be a little slower, not a big deal, to be honest. And also, you are writing HTML inside the string. When your HTML is like, let's say clean and semantic, it's not a big deal.

[00:22:38]
But if you have a very large HTML, tables and lots of tips, and it's difficult to actually even even VS Code is not using the right colors for HTML, it's just a string. So if you have an error, if you are not closing your tags, you will not realize that.

[00:22:55]
I mean, if you have that problem, I mean, I'm not closing the h2 in the right way, or I'm closing h6 here, so this is wrong, but I'm not seeing any error because it's just a string. And when you have it in the HTML, you can use the tools to help you with that, so those are the differences.

[00:23:09]
The final result will be the same.

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