Angular Cheat Sheet

By Syncfusion®, Inc. · Last updated

A short reference of the whole course: structure, components, templates, binding, directives, pipes, forms, services, DI, routing, RxJS, HTTP, signals, state, render modes, security, errors and performance.

Angular Application Structure

File or folderPurpose
src/main.tsStarts the app: bootstrapApplication(App, appConfig)
src/index.htmlThe page that contains <app-root>
src/styles.cssGlobal styles
src/app/app.tsThe root component
src/app/app.config.tsApp-wide providers: router, HttpClient, error handler
src/app/app.routes.tsThe list of routes
public/Static files, such as images and favicon.ico
angular.jsonBuild settings, budgets, environments
CommandWhat it does
ng new my-appCreates a project
ng serveStarts the development server on http://localhost:4200
ng buildBuilds the app for production into dist/
ng generate component nameCreates a component (ng g c name)
ng generate service nameCreates a service (ng g s name)
ng generate environmentsCreates the environment files
ng add @angular/ssrAdds server-side rendering

Components

import { Component } from '@angular/core';

@Component({
  selector: 'app-product-card',   // used as <app-product-card />
  imports: [CurrencyPipe],        // components, directives, pipes used in the template
  templateUrl: './product-card.html',
  styleUrl: './product-card.css',
})
export class ProductCard {
  name = 'Keyboard';
}
PropertyPurpose
template / templateUrlInline HTML / HTML file
styles / styleUrl / styleUrlsInline CSS / one CSS file / several CSS files
encapsulationViewEncapsulation.Emulated (default), None, ShadowDom
changeDetectionChangeDetectionStrategy.Default or OnPush
providersComponent-level services
CSS selectorSelects
:hostThe component's own element
:host(.selected)The host element when it has a class
:host-context(.dark)The component when a parent has a class
var(--brand-color, #c3002f)A CSS custom property with a default

Templates

SyntaxMeaning
{{ name }}Interpolation: show a value
{{ user?.name ?? 'Guest' }}Optional chaining with a default
@if (cond) { } @else if (x) { } @else { }Conditional block
@for (item of items; track item.id) { } @empty { }Loop with tracking and an empty state
@switch (value) { @case ('a') { } @default { } }Switch block
#inputTemplate reference variable
<ng-container>Groups elements without adding an element
<ng-template>Content that is not rendered until it is used
<ng-content />Shows content passed between the component's tags

Data Binding

BindingSyntaxDirection
Interpolation{{ value }}Class → template
Property[disabled]="isBusy"Class → element
Attribute[attr.aria-label]="label"Class → HTML attribute
Class[class.active]="isActive"Class → CSS class
Style[style.width.px]="width"Class → CSS style
Event(click)="save()"Element → class
Two-way[(ngModel)]="name"Both directions

Directives and Pipes

DirectiveExample
ngClass[ngClass]="{ active: isActive, error: hasError }"
ngStyle[ngStyle]="{ color: textColor }"
*ngIf (older)<p *ngIf="loggedIn">Hi</p>
*ngFor (older)<li *ngFor="let o of orders; trackBy: trackById">
Custom attribute directive@Directive({ selector: '[appHighlight]' })
PipeExampleResult
uppercase / lowercase{{ 'hi' | uppercase }}HI
titlecase{{ 'asha rao' | titlecase }}Asha Rao
currency{{ 49.9 | currency }}$49.90
number{{ 3.14159 | number: '1.0-2' }}3.14
percent{{ 0.25 | percent }}25%
date{{ today | date: 'longDate' }}November 6, 2026
slice{{ text | slice: 0:10 }}First 10 characters
json{{ user | json }}The object as JSON text
async{{ data$ | async }}The latest value of an Observable
@Pipe({ name: 'initials' })
export class InitialsPipe implements PipeTransform {
  transform(name: string) {
    return name.split(' ').map(part => part[0]).join('');
  }
}

Event Handling

EventExample
Click(click)="add()"
Key filter(keyup.enter)="search()", (keydown.escape)="close()"
Input text(input)="text = $any($event.target).value"
Change(change)="onSelect($event)"
Form submit(ngSubmit)="save()"
Parameters(click)="remove(item.id)"
Stop the browser actionevent.preventDefault()

Component Communication

// Child
@Input() product!: Product;                       // parent → child
@Output() added = new EventEmitter<Product>();    // child → parent
this.added.emit(this.product);
<!-- Parent -->
<app-product-card [product]="selected" (added)="addToCart($event)" />

<!-- Two-way: @Input() size + @Output() sizeChange -->
<app-font-size [(size)]="fontSize" />

Lifecycle Hooks

HookRuns
constructorWhen the class is created. Inject services here
ngOnChanges(changes)Before ngOnInit, and when an @Input() gets a new value
ngOnInit()Once, after the first inputs are set. Start loading data here
ngDoCheck()On every change detection run
ngAfterContentInit()Once, after projected content is ready
ngAfterContentChecked()After every check of projected content
ngAfterViewInit()Once, after the component's view is ready
ngAfterViewChecked()After every check of the view
ngOnDestroy()Before the component is removed. Clean up here
afterNextRender(fn)Once, in the browser only, after the next render

Template-Driven Forms and Reactive Forms

PointTemplate-drivenReactive
ImportFormsModuleReactiveFormsModule
Defined inThe template, with ngModelThe class, with FormGroup / FormBuilder
Binding[(ngModel)]="user.name" name="name"[formGroup]="form", formControlName="name"
Best forSmall, simple formsLarger forms, dynamic fields, testing
private fb = inject(FormBuilder);

form = this.fb.nonNullable.group({
  name: ['', Validators.required],
  phones: this.fb.array([this.fb.control('')]),
});

this.form.setValue({ ... });     // all values
this.form.patchValue({ name });  // some values
this.form.reset();
this.form.getRawValue();

Form Validation

ValidatorError key
Validators.requiredrequired
Validators.minLength(8) / maxLength(20)minlength / maxlength
Validators.min(0) / max(100)min / max
Validators.emailemail
Validators.pattern(/^[0-9]{6}$/)pattern
Statetrue when
valid / invalidAll rules pass / a rule fails
touched / untouchedThe user left the field / did not
dirty / pristineThe user changed the value / did not
pendingAn async validator is running
// Custom validator: return null when valid
export function noSpaces(control: AbstractControl): ValidationErrors | null {
  return String(control.value ?? '').includes(' ') ? { noSpaces: true } : null;
}

control.hasError('minlength');
form.markAllAsTouched();          // show all messages on submit
control.setValidators([...]); control.updateValueAndValidity();

Services

@Injectable({ providedIn: 'root' })
export class CartService {
  private readonly _items = signal<string[]>([]);
  readonly items = this._items.asReadonly();

  add(item: string) {
    this._items.update(list => [...list, item]);
  }
}

// In a component
private cart = inject(CartService);

Dependency Injection

ProviderGives
CartServiceA new CartService
{ provide: A, useClass: B }A B when A is requested
{ provide: TOKEN, useValue: 20 }A fixed value
{ provide: A, useFactory: () => new A(1) }The result of a function
{ provide: Old, useExisting: New }The same object as New
export const API_URL = new InjectionToken<string>('API_URL');
providers: [{ provide: API_URL, useValue: 'https://api.shop.com' }]
url = inject(API_URL);
analytics = inject(AnalyticsService, { optional: true });  // null if not provided
WhereScope and lifetime
providedIn: 'root'One object for the app, until the app closes
Component providersOne object per component, removed with it

Routing

export const routes: Routes = [
  { path: '', redirectTo: 'home', pathMatch: 'full' },
  { path: 'home', component: Home, title: 'Home' },
  { path: 'products/:id', component: ProductDetail },
  { path: 'settings', component: Settings, children: [{ path: 'profile', component: Profile }] },
  { path: 'admin', canActivate: [roleGuard], data: { roles: ['admin'] },
    loadChildren: () => import('./admin/admin.routes').then(m => m.ADMIN_ROUTES) },
  { path: 'reports', loadComponent: () => import('./reports/reports').then(m => m.Reports) },
  { path: '**', component: NotFound },
];

provideRouter(routes, withComponentInputBinding())
TaskCode
Outlet<router-outlet />
Link<a routerLink="/products" routerLinkActive="active">
Link with parameter[routerLink]="['/products', product.id]"
Query parameters[queryParams]="{ category: 'audio' }"
Navigate in codeinject(Router).navigate(['/orders', id])
Read a parameter@Input() id = ''; (with withComponentInputBinding())

RxJS Fundamentals

APIPurpose
of(1, 2), from([...]), interval(1000)Create Observables
source$.subscribe({ next, error, complete })Receive values
sub.unsubscribe()Stop receiving
pipe(map(), filter(), tap())Change, filter, side effects
switchMap()Switch to a new request, cancel the old one
catchError() / finalize()Replace an error / run at the end
Subject / BehaviorSubjectSend values / send and store the current value
takeUntilDestroyed()Stop when the component is destroyed
{{ data$ | async }}Subscribe in the template

API Integration

provideHttpClient(withInterceptors([authInterceptor]))

private http = inject(HttpClient);
this.http.get<User[]>('/api/users');
this.http.post<User>('/api/users', newUser);
this.http.put<User>(`/api/users/${user.id}`, user);
this.http.delete<void>(`/api/users/${id}`);
this.http.get('/api/users', { headers: new HttpHeaders({ 'Accept-Language': 'en' }) });

export const authInterceptor: HttpInterceptorFn = (req, next) =>
  next(req.clone({ setHeaders: { Authorization: `Bearer ${token}` } }));
StatusMeaning
200 / 201 / 204OK / created / OK with no body
400Wrong request data
401 / 403Not logged in / not allowed
404Not found
500Server error
0No connection

Angular Signals

count = signal(0);                                  // writable
count();                                            // read
count.set(5);                                       // replace
count.update(n => n + 1);                           // from the current value
items.update(list => [...list, item]);              // new list, never push()
double = computed(() => this.count() * 2);          // derived, read-only
effect(() => console.log(this.count()));            // side effect (in the constructor)
readonly value = this._value.asReadonly();          // read-only view

State Management

KindWhere
Component stateA signal in the component
Shared stateA store service with private signals, read-only access and methods
RxJS stateA private BehaviorSubject with asObservable()
Large appsNgRx: actions → reducer → store → selectors
// NgRx
export const addItem = createAction('[Cart] Add Item', props<{ name: string }>());
export const cartReducer = createReducer(initialState, on(addItem, (s, a) => ({ items: [...s.items, a.name] })));
export const selectCount = createSelector(selectCart, cart => cart.items.length);
store.dispatch(addItem({ name: 'Pen' }));

Render Modes

ModeHTML is createdRenderModeBest for
CSRIn the browserRenderMode.ClientApps behind a login
SSROn the server, per requestRenderMode.ServerPublic pages with changing data
SSGAt build timeRenderMode.PrerenderDocs, blogs, marketing pages
// app.routes.server.ts
{ path: 'docs/:slug', renderMode: RenderMode.Prerender,
  async getPrerenderParams() { return DOCS.map(d => ({ slug: d.slug })); } }

provideClientHydration(withEventReplay())   // app.config.ts
isPlatformBrowser(inject(PLATFORM_ID))      // browser or server?
afterNextRender(() => { /* browser-only code */ });

User Access Control

ConceptSummary
AuthenticationWho is the user? (login)
AuthorizationWhat may the user do? (roles)
JWTheader.payload.signature, sent as Authorization: Bearer <token>
ExpirationThe exp claim, in seconds; log out when it passes
export const authGuard: CanActivateFn = () =>
  inject(AuthService).isLoggedIn() ? true : inject(Router).createUrlTree(['/login']);

{ path: 'admin', component: Admin, canActivate: [roleGuard], data: { roles: ['admin'] } }

Always check permissions on the server too.

Error Handling

ErrorHandle with
Missing value?., ??, @if
A function can throwtry { } catch (error) { } finally { }
HTTP request failscatchError() or the error callback
Unknown URL{ path: '**', component: NotFound }
Missing provider (NG0201)providedIn: 'root' or providers
Everything elseA custom ErrorHandler
@Injectable()
export class AppErrorHandler implements ErrorHandler {
  handleError(error: unknown) {
    console.error(error);        // developers
    // log to a server, show a fallback message to users
  }
}

providers: [{ provide: ErrorHandler, useClass: AppErrorHandler }]

Look up NG error codes at angular.dev/errors.

Performance Optimization

TechniqueCode
Lazy loadingloadComponent / loadChildren
Budgets"budgets" in angular.json
OnPushchangeDetection: ChangeDetectionStrategy.OnPush
New objects for inputsthis.item = { ...this.item, price: 30 }
No heavy methods in templatestotal = computed(() => ...)
Track list items@for (o of orders; track o.id) / trackBy: trackById
MeasureLighthouse, Performance tab, Angular DevTools Profiler, performance.now()