- In this section
we're going to start looking at components in more detail.
It's important that you understand how components work,
what are they,
so that we can test them later on.
So in an Angular application, a component is a class
that has data and renders that data in an HTML page.
So a good way to think about it is like this:
We have a class,
a component class that has some data,
and the component class has an associated HTML template file
which displays the data contained inside the component.
So when you create an application initially
with the Angular CLI,
it creates just one component, a class called app component,
which is just kinda like the root part component
in your application.
What we'll do now in this section
is we'll see how to create additional components.
A typical Angular application will have
dozens or hundreds of components,
each component represents one part of the user interface.
So for example, you might define a component
called header, or footer,
or menu bar, or advertising panel.
So each component is a separate class with its own data
and its own html fragment to display part of your webpage.
The whole webpage is like a joining together
of all the components.
A component's like a jigsaw piece in the bigger jigsaw.
So we're gonna look at an example,
Example4/HelloWorld,
I've already written that example, and then here it is.
A usual kind of arrangement in the src folder,
the interesting code is in the app folder.
As you will see, I have generated another component
called header.
We're gonna have a look at the header component in a moment,
before we do that, just a quick reminder,
each component has 4 files.
A file that defines the component class,
a file that renders the- that can test it,
a file that renders the component as HTML,
and a file that styles the HTML to look nice.
So each component has 4 files,
and they all have the same kind of name,
app.component,
the class, the test,
the HTML template to display it,
and the CSS StyleSheet to make it look nice.
So the application component is in many ways
a special component, it is the root component
in your application,
so it lives kind of directly in the app folder,
but when you create other components
like header and footer, they get put by default
into a separate sub-folder,
so I'll show you how I did this in a moment,
I generated a component called header,
it was put into a separate folder, but it also had 4 files.
Every component has 4 files,
and every component goes into a folder with the same name,
apart from the app component which is kind of like
sitting at the top level.
So I've generated another component called header,
let's see how to do that.
To generate a component, you open up a command window,
you run the Angular CLI NG and you generate a component.
A bit earlier we generated a class,
now we're going to generate a component.
Always use lowercase letters and hyphens for the names.
This generated the header component,
and as you've just seen it created a folder
called- underneath src/app,
the Angular CLI always puts the components into a folder
named after the component.
And in there, it generated 4 files.
The component class,
an HTML template to display it's data,
A CSS StyleSheet for styling purposes,
and a test spec to test the code in our component class.
Okay, so we've seen that,
I'm going to create another component
just because I want to.
So I'm gonna go into the example for HelloWorld folder,
I'm going to generate a new component.
If I can have a header component, then maybe
I can also have a footer component.
Let's generate a new component called footer,
it will create a folder called footer,
well src/app/footer,
and in there it will generate the 4 files.
The footer TypeScript file,
plus the spec,
plus the HTML template to display it,
and the StyleSheet to style it.
So we can see in the footer folder,
its created those 4 files.
Also, interestingly, it added my component into the module.
I mentioned the module a bit earlier,
the module is kinda like a container,
it's a special class in an Angular application
that basically defines all of the components
in your application.
When an application starts in Angular,
pretty much the first thing it does is to look in the module
to see what components do you have in your application.
So the module registers all components,
so the Angular CLI tool has automatically updated the module
to include a reference to my component,
that's quite nice.
The module needs to know about every component
in your application,
so basically it knows how to create them
in the user interface.
So we'll have a look at that in a moment.
Right, so here is the code that's generated by default
for a component.
So for the header component, in src/app/header,
this is the source code for the component class.
The name of the class here, HeaderComponent,
it implements an interface.
TypeScript has interfaces,
and there's an interface called OnInit.
We'll talk about this later on, it's kind of like
when a component is created the OnInit interface
allows you to do some additional initialization
just before the component is rendered,
basically to receive input parameters.
So anyway, this is the code it has generated,
my component implements the OnInit interface,
and that's why it has this method here.
This method is specified by the OnInit interface.
You can put code in here to do additional component
that basically runs after your constructor.
When your component is created
to be displayed in the webpage,
Angular will call the constructor
to initialize the component,
and then a bit later it will call the ngOnInit method
to do any additional initialization
just before the component is rendered on the page.
Okay, so there we are, there's some theory we will
need to come back to later.
Notice that the component is decorated
by a component decorator.
In Angular, or rather in TypeScript,
this syntax is called a decorator,
it's a bit like an annotation in Java,
or a decorator in Python,
or an attribute in C#.
What it does is it metadata about your component,
so this decorator syntax here,
it basically qualifies the component class,
specifically it says,
what does it say?
It says there will usually be data in your component,
and that data needs to be displayed,
this is the name of the HTML file that it will use,
Angular will use, to display your data.
In the current folder,
it will pick up header.component.html,
that HTML file will basically render whatever data
you might have in here.
That's client side data-binding
so that's important.
By the way, you can have some StyleSheets,
it will say these are the CSS files that it will apply
just for this component.
If your component has it's own particular styling
just for headers, you can put them into
your header.component.css,
and that CSS will automatically be imported
into the HTML to give it some nice appearance.
And then finally, and this bit will become more apparent
in a few minutes, we also have a selector.
The selector here is like a tag name,
and the way it works is components get created by Angular
when Angular sees the selector,
so this basically says this selector corresponds
to that class.
What that means, if some other component
somewhere in the webpage said this:
app-header,
it's XML syntax so you'd have to make it like this,
end app-header,
basically the selector says this is the tag name
that you need to use to create this component.
So when Angular is rendering your application,
whenever it sees this selector,
it will know to basically display your component.
So that's what the selector says, use this tagname
to create an instance of this component
using this kind of syntax up here.
Okay, so hopefully that makes sense,
I guess the next thing we can do is to have a look
at the HTML file and the StyleSheet
to see what is actually going to be rendered.
Whenever this components rendered, it will basically
invoke the HTML to display- to figure out what to display.
So let's have a look at the HTML file and the CSS.
So here's the HTML,
this was generated by Angular CLI in the header folder,
because it's the header component.
Here is the HTML template for the header component,
and it just says that.
Obviously the idea was you could put something
more interesting in here,
but that was the HTML template that was generated for us.
What about the StyleSheet?
The StyleSheet, well it's empty at the moment,
do you like my color scheme?
I've got yellow for code, green for HTML,
and pink for StyleSheets.
So at the moment, my header CSS is empty,
it doesn't need any particular styling.
So, I mean to be honest in that case, why bother having it?
So I'm gonna edit my code actually.
I'm gonna go to my code for my header component,
note this, there's a footer component as well,
I'm gonna go into my header component
and if this StyleSheet is empty,
in fact what I'll do is I'll actually define,
let's have a look at the HTML here.
It says there's a paragraph "header works!", okay,
"My uber cool header works!", it's a paragraph,
I can define a style here just for my header component
to say anywhere in that header component
where there's a paragraph element,
then set the background color-
set the text color to be red,
and set the background color to be green,
and set the font size to be, well,
if you want the font size to be twice the normal font size
you can say 2em,
and em is the standard size of the font,
2em is twice the font size.
Let's make it 5 times the font size
so that it's very prominent,
so this style, this set of styles here,
will only apply to this component.
Good, it's gonna be beautiful.
Right, now then, here's there thing.
There's this module in Angular,
when an Angular application starts it needs to know
about all the components in your application,
and it's the module that tells it that information.
So this is the module file, we haven't seen this before,
in the src folder, there is one app.module at the moment,
you can have multiple modules actually for modular design,
but we have one module here,
it's a class called AppModule.
Not that that's particularly revelatory,
the important thing here is the decorator that decorates it.
This decorator is actually the important thing.
The NgModule decorator,
which I've just partially overwritten, excuse me,
it specifies the declarations property here,
this is an object syntax by the way,
the declarations property lists all of the components
in your application.
The module needs to declare what components
are part of your application.
There are also some other details here
that we need to get on to,
the ability to run the application in a browser,
providers is to do with service injection,
we'll talk about that later,
bootstrap, that's important, you can imagine
in like when you have a C++ application, or C# or Java,
when you run it one of the functions is the main function
that gets executed, so it's obviously the main function.
But in an Angular application you've got lots of components,
and you have to basically tell Angular which component
is the top level component that should be rendered first.
That's what bootstrap means, it says of all these components
you've got, what is the main component to run initially?
AppComponent, that's the top level component.
These components here have to be imported,
import the app component from the src file,
import the header component from the src file.
Obviously if you didn't import these symbols
you'd get compiler errors here,
it wouldn't know what you're talking about.
Now interestingly in my example,
I've also got a footer component.
So if you have a look,
the footer component is,
you know, the code is the same as the header basically,
but have a look at the module.
Remember, when I added my footer component
Angular CLI automatically enhance my module specifier
to include my footer, it did that automatically,
okay so here's my AppModule class,
that's not the important bit,
the important bit here is the fact that it's decorated
with this NgModule decorator.
It declares an array of all the components
including the footer component.
Don't forget the import statement,
otherwise it's not gonna like it.
Okay, lets add that back in again.
If you want to you can just tidy this code up a bit,
because the application's quite simple,
I've only got 3 components at the moment
so I could just write it like that,
and that might make it a bit easier to read.
The imports list, you can run module
can import other modules as well.
So you might prefer that syntax,
but as your application grows
you're gonna have dozens of components,
so it kinda makes more sense to list them like that,
it's easier to read listing them vertically.
Right, well anyway, that's the module.
The module needs to know, or it needs to advertise
all your components in your application.
Right, so another closer look, just a reminder,
in our header component each component has a selector,
and that selector basically means use this as an XML tag
to create an instance of this component.
So the application component, when we our header component
the Angular CLI automatically changed
my application component, the top level component,
like this.
Basically in the app.component, the top level component
you can use this syntax, app-header.
It will basically- when this HTML template is rendered
it will see this syntax and it will know that that tag name
corresponds to this header component,
so this tag here is basically like saying
create a new instance of the header component and render it,
it will create this object,
generally this object will have data,
and that data will be data-bound into the HTML
and then displayed by the HTML.
So an interesting thing would be
what if I had more than 1 app-header?
So if I go to my application component,
here's my application component,
we haven't seen this before,
it's got some simple data plus its own template,
its own HTML template,
let's have a look at that file.
In that file it says display the title,
now this syntax here is data-binding,
and we'll have a look at that later,
it grabs that title from the corresponding component.
If we're in app.component.html
then it'll go to the corresponding component class,
which is that one,
and in there it will look for a data field called title.
That's data-binding, it gets that data
from the component class.
So that title there is what's going to be displayed here.
So what I'm going to do,
I'm actually gonna change my component to say
name = 'Andy',
and we'll have nationality, I don't know if
I've mentioned this but I'm Welsh.
I think I might've dropped that into the conversation
at some point.
So I've changed my component to have some other data now,
a name property and a nationality property,
and I'm gonna go into my template to display it.
Let's go to display name,
it's gonna say this:
"Hi name".
Comma, very grammatically correct.
"Your nationality is", and then here data-binding syntax.
Open double curlies, closed double curlies,
and inside here, a property from your component class.
I called it nat, didn't I?
You get IntelliSense as well, it's quite smart,
I'm using Visual Studio Code.
So that will say "Hi Andy, your nationality is Welsh."
"Congratulations!"
And then it's gonna run off my app-header component
like that.
So guess what we need to do now is to
actually run the application, we need to do an ng serve.
It will build the application,
open up a development web server,
and then you can browse to localhost:4200.
Oh wow, that's beautiful!
It said this is the application component,
"Hi Andy, your nationality is Welsh, congratulations!"
Nice one mate.
And here's my header component,
my header component had a StyleSheet, remember?
So remember my header component.
So first of all when it sees this,
it will say right, I'll render the header component,
it knows that that corresponds to the header component.
The header component has that data,
well no data actually,
and it has that HTML "my uber cool header works"
and also it applies that StyleSheet.
Almost done here, question for you,
what if in my top level HTML I have multiple headers,
what happens if I do this?
Well you know what's gonna happen, don't you?
Basically every time you use that tag
Angular will create a new instance of the header component
and render it,
so I'm gonna have the same output 3 times now.
Oh good, and just so it doesn't feel left off,
I had a footer component, remember?
And the footer component, its selector was app-footer.
I mean you can change that if you want,
you just need to know what it is,
that's the selector that we need to use
to instantiate the footer.
The footer was quite mundane, but at least it exists.
So let me go back to my top level app component,
and let's have, I know, let's have a horizontal rule,
and then we have the app-footer.
IntelliSense, it knows what components I've got,
it's great isn't it?
App-footer.
I think we'll just have one app-footer
because it's a bit boring.
Save the file, when you do an ng serve
it has a live connection to your code,
so as soon as you save the file it will rebuild it
and then redisplay it.
Okay, so there we go, so that's done.
So my header picked up some data,
my application component,
here's my header instantiated 3 times,
and my footer at the bottom.
So now you've got a good understanding
of how components work,
I think now we're ready to start looking
at how to test them.