Component-Based Architecture in AngularJS 1.x and ES6 Exercise 2 Solution
This course has been updated! We now recommend you take the Angular 9 Fundamentals course.
Transcript from the "Exercise 2 Solution" Lesson
>> Scott Moss: So the objective was to eventually have something like this. So if you were the observant person, you might have noticed I have like this hash up here, right? So if you've ever used Angular, then you know there's some router stuff going on here. So I don't know if anybody noticed that but that definitely means I am using router somewhere.
[00:00:23] So that was a hint, I don't know if you picked that up. Great, so you should have this, we have some styles and some stuff going on here. So how did we get to this? So let's check it out, let's look at the code. So you can check out step-2-fix to follow along or you can just look up here, but let's look at it.
[00:00:40] So let's start in app.js. I heavily commented this bad boy out cuz I knew there's some weird stuff going on in here and I wanted to explain it as much as I can. So if you look through this solution you'll see tons of comments of what's going on as we walk through this code.
[00:00:55] So the first thing I did was [COUGH] I imported normalize.css. So I didn't tell you how to do this. I didn't tell you that you didn't have to put a variable in the from keyword. So if you found that out, good for you, because you're right, you don't have to do this.
[00:01:07] And the reason we don't have to do it is because if we read this comment above, what happens is with the style loader its job is to take a style, a CSS file, and place it in the head. All right, that's what it does, it places in the head, and if you don't believe me, let me show you.
[00:01:26] Open this up, the console, I go to elements, I'll look in the head, look all this styles. So here is my code which means this should be normalized CSS. There it is there's normalize CSS, it placed all that in the head for me in the order that I imported it.
[00:01:41] So that's why we don't need a variable followed by the import. And we also don't need the from keyword either. So we can just exclude those two. Now, for whatever reason you wanted to just import that CSS file as just raw text. You can do that as well, you would just have to set up the loader for that.
[00:02:04] So we have this other plug in called raw which allows you to import raw text. You would just have to place the stuff in there as well so you can import it as raw text. But we didn't want that, we wanted to put in the head cuz we're lazy and we don't want to write a link tag.
[00:02:17] All right, yes?
>> Speaker 2: So wait, Scott, can you walk through a little bit slower how that CSS is getting into the head? What is signaling that in the webpack config, or in the Gulp file?
>> Scott Moss: Yeah for sure, so how is this CSS actually getting in the head right?
[00:02:30] What's doing this, whose job is it, what's going on, right? So this is not ES2015 that's doing this. So let's start with this, this is ES2015 syntax as far as importing it, right? That's all that's happening with ES2015. And then I'm importing because we know that this is going to compiled down to common JS and I didn't put a dot forward slash in front of it.
[00:02:53] That means I'm importing something from the node modules folder. It just so happens that the name of this something has a .css after it. This is really confusing, I actually put this specific module in here to confuse people. Because you're gonna immediately think that it's a file because it's called .css but it's not, it's a node module.
[00:03:16] So if we go look at the modules folder, there is a node module called normalize.css. That's the name of the folder, it's really confusing. Where is that at?
>> Scott Moss: There it is right there, normalize.css. See that's the name of it, they did they did that just to trick us.
[00:03:36] So I'm importing that node module.
>> Speaker 3: Wait, so they were just sitting there thinking we're gonna name it to trick you?
>> Scott Moss: No, no they did it so you'd know specifically it's CSS. And it makes sense because if you think like, wait npm, why is there a CSS package on npm?
[00:03:51] So, it made sense that they called it normalize.css. But it's really confusing when you're doing this cuz you think you're importing a CSS file, which eventually you are. But you're actually importing a module that references the CSS file. So, that's a very important detail there. So we're importing a module called normalize.css, which if you go look at its package.json, it's pointing to a normalize.css file, yes?
>> Speaker 4: Just a quick question, so if you want to use some other CSS file that they didn't publish to npm. Do you normally wrap that in a module and then try to do it this way?
>> Scott Moss: Nope, you do exactly like what we did on line six and we'll get there in a minute.
[00:04:30] So that's how that's happening, we're importing a module. So if we're clear on that, then I'll walk through how this is getting in the head. So we're importing a module, which if you go look at this module's package.json just points to a CSS file. So now we have a CSS file and and it's extension is .css.
[00:04:47] So if we go look in the webpack.config, we have a loader that says test anything with an extension .css which is the normalize.css file. So it's like okay I found one, what should I do with it? First, run it through the CSS loader, which, like I said, normalizes all the URLs and the paths, if any.
[00:05:07] And then, after that's done, run it through the style loader, which does the job of placing it in the head. That's what the style loader does. So the style loader will place it in the header for us. If I got rid of the style loader, it will not place it in the head.
[00:05:20] So that's what the webpack is doing that, JSPM does this as well. The syntax for this is a little different, but it also does this. So that's what's happening on my import normalize.css. Now, a little different thing is happening when I import app.styl. So app.styl is a stylus file.
[00:05:38] So we also eventually want it in the head, but at first we have to convert from stylus. So I just made a different loader that does the exact same thing as this. But first converts it from stylus using a stylus loader.
>> Speaker 2: And this loader is what knows to put it in the head, webpack?
>> Scott Moss: Yes, yep, so if you were to look at the documentation for that. If you just Google style-loader, it will, that's exactly what it does. It's like, I take a CSS file, I stick it in the head, yes?
>> Speaker 4: Do they read in reverse order?
>> Scott Moss: They read from right to left.
[00:06:09] So it's gonna go here first, then here, then here. So convert the stylus to CSS, normalize the paths and stuff, place it in the head. That all happens just by saying import. Right, isn't that trippy, I was like, wait, what?
>> Students: [LAUGH]
>> Scott Moss: You know how much stuff you have to write in Gulp to do that, you know what I mean?
[00:06:34] Like if you've ever written CSS preprocessing code in a build task, then you know that you got to write some code for that. I mean that was easy, that was free almost, right, it was free. So any questions on how this stuff happen in a head. Or any question why I put this first and before anything else?
[00:06:53] So with use of webpack, cuz it's common JS, all these imports are synchronous. JSPM handles imports asynchronously, so it doesn't matter how you import them, they're gonna come at whatever order they want. This is another reason why I decided not to use JSPM, cuz explaining that and having to deal with the nuances will be really difficult during the workshop.
[00:07:12] So webpack, everything is synchronous so we're guaranteed to have normalize.css loaded up and done before the next line is executed, which is great. So that means now I can figure out when I need to load up my CSS. You can imagine if I was using something else that was asynchronous, I would not be guaranteed that normalize.css will load up before my app.style would, which would probably cause some problems with CSS.
[00:07:33] So you have to like write a directive, that like waits, like it's really crazy, I've done it. So this is synchronous, so just like you would in a link tag, you would put this normalize.css first. Cuz this is the CSS that's gonna normalize the styles on all the browsers.
[00:07:47] And then we load up our styles, same thing, all right.
>> Speaker 2: A question from Horatio H., if we had another route, what would happen if we changed from the home route, would it delete the style from home.
>> Scott Moss: No it's going to stay in the head forever. It's never going to remove it, good question.
>> Speaker 6: Unless the route is not a child right?
>> Scott Moss: Unless the route is not a child.
>> Speaker 6: So if it's a sibling to the route, so it's on the same level and not the child or a nested view? [COUGH]
>> Scott Moss: No, it's still never ever moving, it's never gonna remove the stuff from the head ever.
[00:08:22] And in fact they might put it there twice. So if the app.js, if there was another parent above app.js that required or imported app.js. And then there was a sibling of that parent that also imported app.js. That means the import for app.style and the import for nomalize.css is gonna happen twice.
[00:08:39] So they both will be in there twice.
>> Speaker 6: So you need to be mindful of that [CROSSTALK].
>> Scott Moss: You have to be mindful of that, exactly. Yes, so it'll never remove it, but it will add it more than once.
>> Speaker 6: Okay.
>> Scott Moss: Yeah.
>> Speaker 6: Is that, sorry to get off track, but JSPM, is that why it's asynchronous?
>> Scott Moss: Exactly.
>> Speaker 6: To be able to handle.
>> Scott Moss: Yep, that's exactly right and that's what the spec is. It's supposedly asynchronous, but packages, like I said, it's common JS, it's caching this stuff.
>> Speaker 6: Okay.
[00:09:13] I don't want my CSS waiting on Angular to come in before it loads up just like you would in the index.html. So that's why I loaded it first. All right, so then down below, these are just common JS modules here, right? So we went over this, you can name them whatever you want and you import them from whatever name they are.
[00:09:31] So import angular from angular, uiRouter from ui-router and ngAnimate from angular-animate. I'm curious, did anybody log these and see what the values were, when they imported these auxiliary modules? Because if you console log angular, then you know it's an object, it's an angular object. But these two are not objects.
[00:09:50] Does anybody know what they are?
>> Speaker 7: They gotta be strings if they're used in the conclusion.
>> Scott Moss: Exactly, very observant, they're just strings. That's how angular conventions are. What they do is instead of exporting the module, they export the name of the module. So you can just go ahead and place it in here.
[00:10:07] Which in my opinion is really cool cuz now you don't need to remember the name anymore. You just like I'm just gonna put the variable in there. I don't care what the name is anymore, it's just the variable. They change the name tomorrow, it doesn't matter, my code's still gonna work, right.
[00:10:19] Yeah, so I really like that, you don't have to remember names anymore. All right, this thing go crazy full screen. Okay, so these things are just strings. So uiRouter is a string, ngAnimate's just a string. Here's the funky one, I don't know if anybody got this far. But now, if you saw there was a to do that says, we need to import components/home.
[00:10:42] Right, so this is me importing it, so I'm saying import bracket home from components/home/home. Now, for what we've talked about before, I'm importing it like this. Can anybody guess how that's gonna look like on a export?
>> Speaker 8: Export home is the same.
>> Scott Moss: It's gonna look exactly the same, exactly.
[00:10:59] So the rule is If I import of these brackets, I'm probably gonna export of the brackets too. Or put the export in front of the assignment expression.
>> Speaker 7: Okay, so I exported the export default home as the name.
>> Scott Moss: If you export default home and then you try to import it like this.
>> Speaker 7: Yeah, I didn't use the brackets when I [CROSSTALK]
>> Scott Moss: Right, then it worked then. Yeah, if you use the brackets on it with the default, it won't work. But if you don't use the brackets, you're fine, yep, because you export default. Sweet, so then I just go ahead and run us through this stuff.
[00:11:28] So because Angular exports the names of its modules, I like to export the module itself. But I can also still benefit from not having to remember the name, cuz all modules in Angular have a name property. So I can just say the modules.name and it's just the name.
[00:11:46] So that's what I did there. But if you want to be like Angular and export the name of the module, you can do that. But I think you're like selling yourself short if you do that, because there's some low hanging fruit on exporting that module. Because now you can import that module into a test and just completely go crazy on that module and test everything about it.
[00:12:02] Where as if you just export the name of the module, how can you test the module independently? You can't, it's just a name, you'd have to like mock it up now. And now you have to say, here Angular, here's the name of this module, can you mock it up for me and give it back to me?
[00:12:13] Or you can just grab it from the file, so. I like to just export the modules and then just call dot name on it. So, that's what's happened there. Any questions on what's happening here so far?
>> Speaker 2: We have a question further clarifying the CSS stuff, Suresh K is wondering, how do we have the CSS emitted in desks/index.html?
>> Scott Moss: Desks slash, so it's not, so a good question. So I think what he's expecting.
>> Speaker 2: It's for like a style tactic in there, yeah.
>> Scott Moss: Right, yeah, it's not what's happening. So what's really happening is, if you go look in the bundle.js, it's get big now.
>> Students: [LAUGH]
[00:13:17] It's being dynamically rendered on the page via the bundle.js.
>> Speaker 7: So I have a question, maybe you're going to get to this or not. But if I don't explicitly import the home style file, I don't get the home styles?
>> Scott Moss: Nope, if you don't import the style file, you don't get no styles.
>> Speaker 7: Okay, right. You're not importing it in app?
>> Scott Moss: Nope.
>> Speaker 7: Right, and I don't see where it does get imported otherwise?
>> Scott Moss: Maybe you have to import it? [LAUGH] We'll get there, we're going to get there.