Basics & Architecture
What Angular is, what a component is, modules vs standalone, and the four bindings.
What is Angular?
A complete front-end framework from Google, built on TypeScript, with routing, HTTP, forms, dependency injection and RxJS included.
| Angular | React | |
|---|---|---|
| Type | Framework — it's in charge | Library — you're in charge |
| Included | Router, HTTP, forms, DI, RxJS | You pick each one |
| Language | TypeScript, always | JS or TS, your choice |
Angular is a full framework rather than a library. TypeScript, dependency injection,
routing, HTTP and RxJS all come in the box, and the CLI generates the structure. That makes it
opinionated — which is the point on a large team, because everyone's code looks the same.
The React side of this comparison is React tutorial Q4.
What is a component?
A class with a decorator that ties it to an HTML template and some CSS. The building block of every Angular app.
@Component({
selector: 'app-order-list',
templateUrl: './order-list.component.html',
styleUrls: ['./order-list.component.css']
})
export class OrderListComponent {
orders: Order[] = [];
title = 'Orders';
refresh() { /* ... */ }
}
A component is four files: the class, the template, the CSS, and a spec file for tests. The
selector is the tag you use it with — <app-order-list></app-order-list>.
What is an NgModule?
A box that groups components, directives and pipes and declares what they're allowed to use.
@NgModule({
declarations: [OrderListComponent], // what belongs to this module
imports: [CommonModule, FormsModule], // what it can use
exports: [OrderListComponent], // what other modules may use
providers: [OrderService] // services
})
export class OrdersModule { }
declarations | Components, directives and pipes that live here. Each one belongs to exactly one module. |
imports | Other modules whose exports you want to use. |
exports | What you make available to modules that import you. |
providers | Services. |
Angular 14+: a component can be standalone: true and import what it
needs directly, with no NgModule at all. New projects default to it — but most existing
codebases, including Angular 9 ones, are NgModule-based.
"'app-x' is not a known element" almost always means the component isn't declared in this module, or its module isn't imported, or it isn't exported by the module that declares it.
The component's HTML, plus Angular's own syntax that it compiles into DOM instructions.
<h2>{{ title }}</h2> <!-- interpolation -->
<button [disabled]="loading">Refresh</button> <!-- property binding -->
<button (click)="refresh()">Go</button> <!-- event binding -->
<div *ngIf="orders.length"> <!-- structural directive -->
<p *ngFor="let o of orders">{{ o.total | currency }}</p> <!-- pipe -->
</div>
Either templateUrl for a separate file, or template for a short inline
one.
The four types of data binding
<p>{{ user.name }}</p> <!-- 1. interpolation, text only -->
<img [src]="user.avatar"> <!-- 2. property, any value -->
<button (click)="save()">Save</button> <!-- 3. event -->
<input [(ngModel)]="user.name"> <!-- 4. two-way -->
[(ngModel)] is just property binding and event binding together —
[ngModel]="x" (ngModelChange)="x = $event". Knowing that is the answer to
"how does two-way binding actually work?". It needs FormsModule.
{{ }} always produces a string. src="{{ url }}" works
for a URL, but disabled="{{ false }}" sets the attribute to the text
"false" — which is truthy. Use [disabled]="false" for anything that
isn't text.
How do parent and child components communicate?
// child
export class OrderRowComponent {
@Input() order!: Order; // data comes down
@Output() selected = new EventEmitter<number>(); // events go up
pick() { this.selected.emit(this.order.id); }
}
<!-- parent -->
<app-order-row
[order]="o"
(selected)="onSelected($event)"></app-order-row>
| Angular | React |
|---|---|
@Input() | props |
@Output() + EventEmitter | callback props |
[(ngModel)] | value + onChange |
For components that aren't parent and child, don't try to wire them up — use a
shared service with a BehaviorSubject (Module 04 and Q56).
Angular 17+: the signal-based input() and output()
functions replace the decorators. Same idea, different syntax.