Angular Cheatsheet
Components, directives, services, pipes, routing, and RxJS patterns for Angular development.
Component Basics
Component decorator
@Component({
selector: "app-hello",
template: `<h1>Hello, {{ name }}</h1>`,
standalone: true,
})
export class HelloComponent {
name = "World";
}Input & Output
@Input() title: string = "";
@Output() clicked = new EventEmitter<void>();
onButtonClick() {
this.clicked.emit();
}Lifecycle hooks
implements OnInit, OnDestroy
ngOnInit() { /* called once after init */ }
ngOnDestroy() { /* cleanup subscriptions */ }ViewChild
@ViewChild("myInput") inputRef!: ElementRef;
ngAfterViewInit() {
this.inputRef.nativeElement.focus();
}Template Syntax
Interpolation
{{ title }}
{{ user.name | uppercase }}Property binding
<img [src]="imageUrl" [alt]="title">Event binding
<button (click)="handleClick($event)">Click</button>Two-way binding
<input [(ngModel)]="username">*ngIf (legacy)
<div *ngIf="isLoggedIn; else loginBlock">Welcome</div>
<ng-template #loginBlock>Please log in</ng-template>@if (new control flow)
@if (isLoggedIn) {
<p>Welcome!</p>
} @else {
<p>Please log in.</p>
}@for (new control flow)
@for (item of items; track item.id) {
<li>{{ item.name }}</li>
}Services & Dependency Injection
Create service
@Injectable({ providedIn: "root" })
export class UserService {
constructor(private http: HttpClient) {}
getUser(id: number): Observable<User> {
return this.http.get<User>(`/api/users/${id}`);
}
}Inject into component
constructor(private userService: UserService) {}
// or with inject()
private userService = inject(UserService);HttpClient
this.http.get<Post[]>("/api/posts");
this.http.post<Post>("/api/posts", body);
this.http.put<Post>(`/api/posts/${id}`, body);
this.http.delete(`/api/posts/${id}`);RxJS Essentials
subscribe
this.userService.getUser(1).subscribe({
next: (user) => this.user = user,
error: (err) => console.error(err),
});Common operators
import { map, filter, switchMap, takeUntil, catchError } from "rxjs/operators";
obs$.pipe(
map(data => data.items),
filter(items => items.length > 0),
catchError(err => of([]))
).subscribe();switchMap (cancel previous)
searchInput$.pipe(
debounceTime(300),
switchMap(query => this.search(query))
).subscribe(results => this.results = results);Unsubscribe with takeUntil
private destroy$ = new Subject<void>();
obs$.pipe(takeUntil(this.destroy$)).subscribe();
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}Async pipe (preferred)
<ul>
<li *ngFor="let item of items$ | async">{{ item.name }}</li>
</ul>Async pipe auto-unsubscribes when component is destroyed.
Routing
Route config
const routes: Routes = [
{ path: "", component: HomeComponent },
{ path: "about", component: AboutComponent },
{ path: "post/:id", component: PostComponent },
{ path: "**", component: NotFoundComponent },
];Router link
<a routerLink="/about" routerLinkActive="active">About</a>
<a [routerLink]="['/post', post.id]">Post</a>Navigate programmatically
constructor(private router: Router) {}
this.router.navigate(['/dashboard']);
this.router.navigate(['/post', id]);Read route params
constructor(private route: ActivatedRoute) {}
const id = this.route.snapshot.paramMap.get("id");
// or as observable:
this.route.paramMap.pipe(
map(params => params.get("id"))
).subscribe(id => ...);Lazy loading
{ path: "admin", loadChildren: () =>
import("./admin/admin.module").then(m => m.AdminModule) }Pipes
Built-in pipes
{{ name | uppercase }}
{{ name | lowercase }}
{{ price | currency:"USD" }}
{{ date | date:"mediumDate" }}
{{ value | json }}
{{ text | slice:0:100 }}Custom pipe
@Pipe({ name: "truncate", standalone: true })
export class TruncatePipe implements PipeTransform {
transform(value: string, limit = 50): string {
return value.length > limit ? value.slice(0, limit) + "…" : value;
}
}#components#services#rxjs#routing#directives