Component:
Components are the base building blocks of the application. It's a place where you can define logic and template altogether that can be reusable in the app. Each component consists of:
- HTML template
- Typescript class
- CSS styles
To define a component we need a @Component() decorator, the decorate allow us to create a component with lots of configurations, here are the most notable ones:
selector: your component element name in HTML templatetemplateUrl: path to HTML template, if you don't specify this option you can define template directly intemplateoptionstylesUrl: path to styles template, can be 1 or manyproviders: Provide component-level service for the dependency inversionchangeDetection: Change detection strategy such asdefaultoronPushencapsulation: Allow option to make your styling global or encapsulated to this component onlystandalone: An option to make a component standalone so it doesn't need to be declared in a moduleimports: Ifstandaloneis enabled, we need to use this option as well in order to add other components in the template
Example:
@Component({
selector: 'app-component',
templateUrl: './your-component.component.html',
stylesUrl: ['./your-component.component.css']
})Directives
Compared to a component, directive is a class that can modify the behavior of an HTML element or a component. directive apply directly to an element so we don't need to declare a template for it.directive also implements lifecycle methods same as a component Most popular directives are:
- Structural directives:
*ngIf,*ngFor - Attribute directives:
ngClass,ngModel
Directive composition API (Angular 15) [Docs](Angular - Directive composition API)
The API lets you apply directives to a component's host element from within the component TypeScript class.
Pipes
Pipes are special functions that are used in HTML templates to transform/modify display values. Pipes can be chained together to output the desired value. By using pipes, you have increased the reusability of the code base by declaring the transformation function once. So it can be used across many templates.
Usage:
<span>{{ date | datePipe }}</span> <!-- Transform Date object into date string -->
<span>{{ totalValue | currency }} <!-- Transform number in to currency string -->Built-in pipes
| Name | Description |
|---|---|
AsyncPipe | Read the value from a Promise or an RxJS Observable. |
CurrencyPipe | Transforms a number to a currency string, formatted according to locale rules. |
DatePipe | Formats a Date value according to locale rules. |
DecimalPipe | Transforms a number into a string with a decimal point, formatted according to locale rules. |
I18nPluralPipe | Maps a value to a string that pluralizes the value according to locale rules. |
I18nSelectPipe | Maps a key to a custom selector that returns a desired value. |
JsonPipe | Transforms an object to a string representation via JSON.stringify, intended for debugging. |
KeyValuePipe | Transforms Object or Map into an array of key value pairs. |
LowerCasePipe | Transforms text to all lower case. |
PercentPipe | Transforms a number to a percentage string, formatted according to locale rules. |
SlicePipe | Creates a new Array or String containing a subset (slice) of the elements. |
TitleCasePipe | Transforms text to title case. |
UpperCasePipe | Transforms text to all upper case. |
Custom pipes
A pipe must have two things:
- A name, specified in the pipe decorator
- A method named
transformthat performs the value transformation.
// kebab-case.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'kebabCase',
})
export class KebabCasePipe implements PipeTransform {
transform(value: string): string {
return value.toLowerCase().replace(/ /g, '-');
}
}Services
Services are a class that have @Injector() decorator so it can be injected in components. Services can be used to call API or to hold application logic and state. [[Services]]
Input
We can pass data to child component using inputs. Angular now has 3 types of input
@Input
We can declare an input in a child component that data can be passed in. By using ngOnChanges() lifecycle, we can get the latest value each time the input changes.
export class CustomCheckbox {
@Input() checked: boolean;
ngOnChanges(changes: SimpleChanges) {
//We can read value each time the input changes
console.log(changes.checked);
}
}Signal input
Serve the same purposes as the original @Input, but with the benefit of signals. Why should we use signal inputs and not @Input()?
- Type safe
- Value can easily be derived and manipulated using signal
computed() - More local monitoring by using
effect()instead ofngOnChanges()
export class CustomCheckbox {
//Optional input
showLabel = input(false);
//Required input
disabled = input.required(false);
}Model input
Model inputs • AngularModel inputs are a special type of input that enable a component to write new values back to parent component.
export class CustomCheckbox {
// This is a model input.
checked = model(false);
// This is a standard input.
disabled = input(false);
}Output
The usage of Output is for notify changes happenning in child component to the parent component
@Output
Takes an EventEmiiter then emit that event to the parent component
import { Output, EventEmitter } from '@angular/core';
// Child component declaration & properties...
@Output() newItemEvent = new EventEmitter<string>();
addNewItem(value: string) {
this.newItemEvent.emit(value);
}After we instantiate newItemEvent EventEmitter. We can now use emit() method to send value to parent component.
<child-component (newItemEvent)="handleEvent($event)">The emitted event in child component will go through parent component handler function handleEvent with the $event argument as the value we have emitted. (newItemEvent) must be the same with the one declared with @Output
Output function
A function based output doesn't rely EventEmitter but still have the same functionality as @Output decorator. Angular now reccomends using output function instead of @Ouput:
- Consistent with new APIs: Aligns with other function based APIs
input()andmodel()signals, thus increase the typing/developer experience - Type safe: Stricter type compared to
EventEmitter. Example:output()without passing type meansvoidtype. Meanwhile,EventEmitter()with no type is considered asanytype - Simpler API: No longer use
EventEmitterwhich inherit from RxJsSubjectclass. #OutputEmitterRefonly has 2 methodssubscribe()andemit() - Less boilerplate code: declaration is now shorter than
@Ouputdecorator
Resolvers
Class based or function based resolvers provide data to a route before navigation.
[[Resolvers]]
Guards
Functions to check whether route is allowed to navigate or not.
[[Guards]]
Routing
Is a module or config function to let user add routing config to application.
[[Angular Routing]]
Modules (NgModule)
[[Modules (@NgModule)]]