Components
Usually we have the AppComponent
, which is the root of the app. Each component
is split into 4 files:
- HTML
- CSS
- TypeScript
- tests
Usually, each component has its own folder. We store them in the app
folder
(that is pregenerated by ng new
) or some subfolders of it.
Here’s the simplest component:
Angular promotes the separation of things into different files, opposed to
frameworks like Vue.js. However, we are able to have HTML/CSS in the ts
file
simply by replacing templateUrl
/styleUrls
with template
/styles
and
providing the HTML or CSS there as a string.
selector
The selector is usually prefixed with app-
to keep us from overwriting HTML
tags.
The selector
does not have to be an HTML tag. It can also be an attribute or a
class:
selector: 'app-root'
- it will match HTML elements<app-root></app-root>
.selector: '[app-root]'
- it will match any HTML element with that attribue, e.g.<div app-root></div>
.selector: '.app-root'
- it will match any HTML element that has theapp-root
class on it, e.g.<div class="app-root"></div>
.
The selector
property is actually not just the way to name the component. It
is a specifier of where to render it. It’s kind of similar to Kubernetes’
Service object and its selector
, which specifies where to send the traffic.
Most often we just specify our own tag for the component.
Data Binding
Output
We can output data with:
The variable to output needs to exist on the component:
Property Binding
The disabled
property of a button is controlled by the allowNewServer
property on our component:
Two-way Binding
In forms, it is useful to bind in two-ways, so that we can control the contents of the input and also read that content.
Here’s an example:
I am able to access username
in the TS code and I am also able to modify it.
Events
We can bind to “native” events with (event)="expression"
. For example:
The onButtonClick
method would have to exist on our component. We could also
put some expression directly in the HTML instead of invoking a method.
Event Details
We can pass an object with event details by including $event
:
Custom Events
Our comonents can emit custom events that the parent of the component can handle:
The parent comonent would attach to that event like this:
The onUserCreated
would be some method defined on that parent. The $event
would be the instance of User
the MyComponent
passed to the event.
We can alias the name of the event similarly to how we can do that in Inputs that I will describe next.
Inputs
In order to allow our components to accept “arguments”, we need to define them, like this:
The parent component would pass data into MyComponent
like this:
Accepting Children
Our components may display some children that would be passed by the parent component. Here’s how to do that.
The component that accepts children needs to have this somewhere in its template:
The children would be passed like that:
If a component does not define <ng-content>
anywhere in its template, any
content that we pass into it is just lost.
@ViewContent
We might need to access some HTML element that is passed to our component as a
child. We can’t do that with @ViewChild,
because it can only be used for elements that belong to our component directly.
There’s another decorator though - @ViewContent
.
Here’s an example:
From the parent we pass some child into SomeComponent
:
From the SomeComponent
(that received the paragraph into its <ng-content>
):
Component Lifecycle
ngOnInit
- fired once the component is initialized. It’s not yet displayed, but the object for it was created in memory (the constructor finished its execution at this point). Accessing DOM elements from here (e.g. via references) might not give us the expected result since they might not be initialized yet. It’s better to usengAfterViewInit
for that.ngOnChanges
- fired when the component is initialized and also each time any property with the@Input
decorator is modified. It is the only hook that receives an argument - these are the changes that Angular found (with current and previous values).ngDoCheck
- run whenever Angular checks for changes in the component. Even if nothing really changed, Angular has to check it first, and this method will be called. The change detection is triggered by various things: events, Promise resolution and others.ngAfterContentInit
- called when the child passed to this component gets initialized (<ng-content>
).ngAfterContentChecked
- fired when the Angular’s change detection finishes checking the child component.ngAfterViewInit
- fired when the component gets rendered on the screenngAfterViewChecked
- fired when the view (including children) has been checked by Angular.ngOnDestroy
- called once the component is about to be destroyed.
Instantiating Components from TypeScript
Normally, we include all the components that we want to render in our template
.html
files. However, in more dynamic scenarios, it might be impossible to
know upfront which components will be needed on a given page. That’s where
Dynamic Components might be used. We’re able to create components within our
TypeScript code and render them on the page.
Here’s how to do it: StackOverflow.
In Angular <13, we’d use ComponentFactoryResolver
. Nowadays, it’s deprecated.