មេរៀន Angular

ពីចំនុចចាប់ផ្តើម រហូតដល់កម្រឹតខ្ពស់ · ភាសាខ្មែរ

Angular 17+ TypeScript ភាសាខ្មែរ ១៥ មេរៀន
ការណែនាំ

ស្វាគមន៍មក​ Angular Course

មេរៀននេះនឹងបង្រៀនអ្នកអំពី Angular Framework ពីការចាប់ផ្តើមរហូតដល់កម្រឹតខ្ពស់ ជាភាសាខ្មែរ។

Angular គឺជាអ្វី?

Angular គឺជា Framework សម្រាប់បង្កើត Web Application ដែលត្រូវបានបង្កើតឡើងដោយ Google។ វាប្រើ TypeScript ជាភាសាសំខាន់ ហើយផ្តល់នូវ tools ពេញលេញដើម្បីបង្កើត application ធំៗ។

០១
ការដំឡើង Angular
Setup, Node.js, Angular CLI
០២
Component & Template
Component, HTML Template, Interpolation
០៣
Data Binding
One-way, Two-way Binding
០៤
Directives
*ngIf, *ngFor, ngClass, ngStyle
០៥
Services & DI
Dependency Injection, Services
០៦
Routing
Router, RouterLink, Guards
០៧
Forms
Template-Driven, Reactive Forms
០៨
HTTP Client
API calls, HttpClientModule
០៩
RxJS & Observable
Reactive Programming, Operators
១០
Pipes
Built-in Pipes, Custom Pipe
១១
Lifecycle Hooks
ngOnInit, ngOnDestroy...
១២
Modules
NgModule, Lazy Loading
១៣
State Management
NgRx Store, Actions, Reducers
១៤
Testing
Unit Test, E2E Testing
១៥
Deployment
Build, Optimize, Deploy
មេរៀន ០១

ការដំឡើង Angular

រៀនពីរបៀបដំឡើង Node.js, Angular CLI, និងបង្កើត project ដំបូង។

តម្រូវការ

ToolVersionការប្រើប្រាស់
Node.js18+JavaScript Runtime
npm9+Package Manager
Angular CLI17+Command Line Tool
VS CodelatestCode Editor

ការដំឡើង Angular CLI

terminal
# ដំឡើង Angular CLI ជា global
npm install -g @angular/cli

# ពិនិត្យ version
ng version

បង្កើត Project ថ្មី

terminal
# បង្កើត project
ng new my-first-app

# ចូលទៅ folder
cd my-first-app

# run server
ng serve --open
ℹ️

ពេល run ng serve, browser នឹងបើក http://localhost:4200 ដោយស្វ័យប្រវត្តិ។

រចនាសម្ព័ន្ធ Project

structure
my-first-app/
├── src/
│   ├── app/
│   │   ├── app.component.ts    ← Component ចម្បង
│   │   ├── app.component.html  ← Template
│   │   ├── app.component.css   ← Styles
│   │   └── app.module.ts       ← Module
│   ├── assets/
│   ├── index.html
│   └── main.ts
├── angular.json
└── package.json
មេរៀន ០២

Component & Template

Component គឺជាផ្នែកសំខាន់នៃ Angular Application។ រៀនពីរបៀបបង្កើត Component និងប្រើ Template។

Component គឺជាអ្វី?

Component គឺជា building block ដែលមានផ្ទុក:

  • Template — HTML ដែលបង្ហាញ UI
  • Class — TypeScript ដែលដំណើរការ logic
  • Styles — CSS/SCSS ដែលរចនា UI

បង្កើត Component

terminal
# ប្រើ CLI បង្កើត component
ng generate component hello
# ឬ short form
ng g c hello

Component Decorator

TypeScript — hello.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-hello',         // ស្លាក HTML
  templateUrl: './hello.component.html',
  styleUrls: ['./hello.component.css']
})
export class HelloComponent {
  title: string = 'សួស្តី Angular!';
  name: string = 'ខ្ញុំ';
}

Interpolation {{ }}

HTML — hello.component.html
<h1>{{ title }}</h1>
<p>ហៅ​ {{ name }} ជំរាបសួរ!</p>
💡

ដើម្បីប្រើ Component នៅក្នុង Component ផ្សេង ត្រូវដាក់ selector <app-hello></app-hello> ក្នុង HTML។

Property Binding

TypeScript
export class AppComponent {
  imageUrl: string = 'https://angular.io/assets/images/logos/angular/angular.png';
  isDisabled: boolean = true;
}
HTML
<img [src]="imageUrl" alt="Angular">
<button [disabled]="isDisabled">ចុច</button>
មេរៀន ០៣

Data Binding

Data Binding ជាប្រព័ន្ធភ្ជាប់ data រវាង Component class និង Template (HTML)។

ប្រភេទ Data Binding

ប្រភេទSyntaxទិសដៅ
Interpolation{{ value }}Class → Template
Property Binding[property]="value"Class → Template
Event Binding(event)="handler()"Template → Class
Two-way Binding[(ngModel)]="value"ទាំងពីរ

Event Binding

TypeScript
export class AppComponent {
  count: number = 0;

  increment() {
    this.count++;
  }

  onKeyPress(event: KeyboardEvent) {
    console.log('Key:', event.key);
  }
}
HTML
<button (click)="increment()">ចុច: {{ count }}</button>
<input (keyup)="onKeyPress($event)" placeholder="វាយអក្សរ...">

Two-way Binding ជាមួយ ngModel

⚠️

ត្រូវ import FormsModule ក្នុង app.module.ts ដើម្បីប្រើ ngModel។

TypeScript — app.module.ts
import { FormsModule } from '@angular/forms';

@NgModule({
  imports: [FormsModule],
})
TypeScript
export class AppComponent {
  username: string = '';
}
HTML
<input [(ngModel)]="username" placeholder="ឈ្មោះ...">
<p>ស្វាគមន៍: {{ username }}</p>
មេរៀន ០៤

Directives

Directives គឺជា instructions ដែលបន្ថែម behavior ទៅ HTML elements ឬ Component។

*ngIf — បង្ហាញ/លាក់ Element

TypeScript
export class AppComponent {
  isLoggedIn: boolean = false;
  userRole: string = 'admin';
}
HTML
<div *ngIf="isLoggedIn">
  ស្វាគមន៍! អ្នកបានចូល។
</div>

<div *ngIf="!isLoggedIn; else loginBlock">
  សូម Login ជាមុន
</div>

<ng-template #loginBlock>
  <p>អ្នកបានចូលហើយ!</p>
</ng-template>

*ngFor — Loop ទិន្នន័យ

TypeScript
export class AppComponent {
  students = [
    { id: 1, name: 'សុផា', score: 95 },
    { id: 2, name: 'មករា', score: 87 },
    { id: 3, name: 'ចន្ថា', score: 92 },
  ];
}
HTML
<ul>
  <li *ngFor="let s of students; let i = index">
    {{ i + 1 }}. {{ s.name }} — {{ s.score }} ពិន្ទុ
  </li>
</ul>

ngClass & ngStyle

HTML
<!-- ngClass -->
<p [ngClass]="{ 'text-red': score < 50, 'text-green': score >= 50 }">
  {{ score }} ពិន្ទុ
</p>

<!-- ngStyle -->
<div [ngStyle]="{ 'color': isActive ? 'green' : 'red', 'font-size': '18px' }">
  ស្ថានភាព
</div>

Custom Directive

TypeScript — highlight.directive.ts
import { Directive, ElementRef, HostListener } from '@angular/core';

@Directive({ selector: '[appHighlight]' })
export class HighlightDirective {
  constructor(private el: ElementRef) {}

  @HostListener('mouseenter') onEnter() {
    this.el.nativeElement.style.backgroundColor = 'yellow';
  }

  @HostListener('mouseleave') onLeave() {
    this.el.nativeElement.style.backgroundColor = '';
  }
}
មេរៀន ០៥

Services & Dependency Injection

Services ប្រើដើម្បីបែងចែក logic ចេញពី Component ដើម្បីឱ្យ code clean និង reusable។

Service គឺជាអ្វី?

Service គឺជា class ដែលផ្ទុក business logic, data, ឬ functionality ដែល Component ច្រើនអាចប្រើបាន។

បង្កើត Service

terminal
ng generate service user
# ឬ
ng g s user
TypeScript — user.service.ts
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'  // ដំណើរការពេញ app
})
export class UserService {
  private users = [
    { id: 1, name: 'ម៉ូហ្គី' },
    { id: 2, name: 'ចន្ថា' },
  ];

  getUsers() {
    return this.users;
  }

  getUserById(id: number) {
    return this.users.find(u => u.id === id);
  }
}

ប្រើ Service ក្នុង Component

TypeScript — app.component.ts
import { Component, OnInit } from '@angular/core';
import { UserService } from './user.service';

@Component({ selector: 'app-root', templateUrl: './app.component.html' })
export class AppComponent implements OnInit {
  users: any[] = [];

  // Inject Service តាម Constructor
  constructor(private userService: UserService) {}

  ngOnInit() {
    this.users = this.userService.getUsers();
  }
}
ℹ️

providedIn: 'root' មានន័យថា Angular នឹងបង្កើត instance មួយ (Singleton) សម្រាប់ app ទាំងមូល។

មេរៀន ០៦

Routing & Navigation

Routing អនុញ្ញាតឱ្យ user navigate រវាង page ផ្សេងៗក្នុង Single Page Application (SPA)។

Setup Routing

TypeScript — app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { AboutComponent } from './about/about.component';

const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'about', component: AboutComponent },
  { path: '**', redirectTo: '' }  // 404 redirect
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule {}

Router Outlet & RouterLink

HTML — app.component.html
<nav>
  <a routerLink="/" routerLinkActive="active">ទំព័រដើម</a>
  <a routerLink="/about" routerLinkActive="active">អំពីយើង</a>
</nav>

<!-- Component នឹងបង្ហាញនៅទីនេះ -->
<router-outlet></router-outlet>

Route Parameters

TypeScript — routing
const routes: Routes = [
  { path: 'user/:id', component: UserDetailComponent }
];
TypeScript — user-detail.component.ts
import { ActivatedRoute } from '@angular/router';

export class UserDetailComponent implements OnInit {
  userId: string = '';

  constructor(private route: ActivatedRoute) {}

  ngOnInit() {
    this.userId = this.route.snapshot.paramMap.get('id')!;
  }
}
មេរៀន ០៧

Forms

Angular ផ្តល់ Forms ពីរប្រភេទ: Template-Driven Forms និង Reactive Forms ដែលសម្រាប់ use case ផ្សេងៗ។

Template-Driven Forms

ងាយស្រួលប្រើ, អ្វីៗភាគច្រើននៅក្នុង HTML template។

HTML
<form #loginForm="ngForm" (ngSubmit)="onSubmit(loginForm)">
  <input
    type="email"
    name="email"
    [(ngModel)]="user.email"
    required
    email
    #emailField="ngModel"
  >
  <span *ngIf="emailField.invalid && emailField.touched">
    Email មិនត្រឹមត្រូវ
  </span>
  <button type="submit" [disabled]="loginForm.invalid">Login</button>
</form>

Reactive Forms

ទំនាក់ទំនងច្រើនជាង, ប្រើ FormBuilder ក្នុង TypeScript code។

TypeScript
import { FormBuilder, FormGroup, Validators } from '@angular/forms';

export class RegisterComponent {
  form: FormGroup;

  constructor(private fb: FormBuilder) {
    this.form = this.fb.group({
      name: ['', [Validators.required, Validators.minLength(3)]],
      email: ['', [Validators.required, Validators.email]],
      password: ['', [Validators.required, Validators.minLength(8)]],
    });
  }

  onSubmit() {
    if (this.form.valid) {
      console.log(this.form.value);
    }
  }
}
HTML
<form [formGroup]="form" (ngSubmit)="onSubmit()">
  <input formControlName="name" placeholder="ឈ្មោះ">
  <div *ngIf="form.get('name')?.invalid">
    ឈ្មោះត្រូវការ (យ៉ាងហោចណាស់ 3 អក្សរ)
  </div>
  <button type="submit">ចុះឈ្មោះ</button>
</form>
មេរៀន ០៨

HTTP Client

Angular ប្រើ HttpClient Module ដើម្បីទំនាក់ទំនងជាមួយ REST API Server។

Setup HttpClientModule

TypeScript — app.module.ts
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  imports: [HttpClientModule]
})

GET Request

TypeScript — api.service.ts
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

interface Post {
  id: number;
  title: string;
  body: string;
}

@Injectable({ providedIn: 'root' })
export class ApiService {
  private url = 'https://jsonplaceholder.typicode.com';

  constructor(private http: HttpClient) {}

  getPosts(): Observable<Post[]> {
    return this.http.get<Post[]>(`${this.url}/posts`);
  }

  createPost(data: Partial<Post>): Observable<Post> {
    return this.http.post<Post>(`${this.url}/posts`, data);
  }

  updatePost(id: number, data: Partial<Post>) {
    return this.http.put(`${this.url}/posts/${id}`, data);
  }

  deletePost(id: number) {
    return this.http.delete(`${this.url}/posts/${id}`);
  }
}

ប្រើក្នុង Component

TypeScript
export class PostsComponent implements OnInit {
  posts: Post[] = [];
  loading = true;
  error = '';

  constructor(private api: ApiService) {}

  ngOnInit() {
    this.api.getPosts().subscribe({
      next: (data) => {
        this.posts = data;
        this.loading = false;
      },
      error: (err) => {
        this.error = 'មានបញ្ហា!';
        this.loading = false;
      }
    });
  }
}
មេរៀន ០៩

RxJS & Observable

RxJS គឺជា library សម្រាប់ Reactive Programming ដោយប្រើ Observable streams។ Angular ប្រើ RxJS ខ្លាំងណាស់។

Observable vs Promise

ObservablePromise
Lazy (ដំណើរការនៅពេល subscribe)Eager (ដំណើរការភ្លាម)
បង្ហាញ value ច្រើនដងបង្ហាញ value តែម្តង
អាច cancel បានCancel មិនបាន
មាន operators ច្រើនoperators តិច

RxJS Operators សំខាន់ៗ

TypeScript
import { of, from, interval } from 'rxjs';
import { map, filter, switchMap, debounceTime, catchError } from 'rxjs/operators';

// map — ប្តូររូបភាពទិន្នន័យ
of(1, 2, 3).pipe(
  map(x => x * 2)
).subscribe(console.log); // 2, 4, 6

// filter — ជ្រើសសម្ងាត់ element
of(1,2,3,4,5).pipe(
  filter(x => x % 2 === 0)
).subscribe(console.log); // 2, 4

// switchMap — ប្តូរ Observable
searchInput$.pipe(
  debounceTime(300),
  switchMap(query => this.api.search(query))
).subscribe(results => this.results = results);

Async Pipe

💡

ប្រើ async pipe ក្នុង template ដើម្បីដំណើរការ Observable ដោយស្វ័យប្រវត្តិ ដោយមិនចាំបាច់ subscribe ដោយខ្លួនឯង។

TypeScript
export class AppComponent {
  posts$ = this.api.getPosts(); // Observable, មិន subscribe
  constructor(private api: ApiService) {}
}
HTML
<div *ngFor="let post of posts$ | async">
  {{ post.title }}
</div>
មេរៀន ១០

Pipes

Pipes ប្រើដើម្បីបំប្លែង data ក្នុង template ក្នុងទម្រង់ដែលចង់ = formatting tools ។

Built-in Pipes

HTML
<!-- uppercase / lowercase -->
<p>{{ 'hello world' | uppercase }}</p>  <!-- HELLO WORLD -->

<!-- date -->
<p>{{ today | date:'dd/MM/yyyy' }}</p>  <!-- 26/03/2025 -->

<!-- currency -->
<p>{{ price | currency:'USD' }}</p>  <!-- $10.00 -->

<!-- number -->
<p>{{ 1234567 | number:'1.0-0' }}</p>  <!-- 1,234,567 -->

<!-- json -->
<pre>{{ user | json }}</pre>

<!-- slice -->
<p>{{ items | slice:0:3 }}</p>

Custom Pipe

TypeScript — shorten.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';

@Pipe({ name: 'shorten' })
export class ShortenPipe implements PipeTransform {
  transform(value: string, limit: number = 50): string {
    if (value.length <= limit) return value;
    return value.substring(0, limit) + '...';
  }
}
HTML
<p>{{ longText | shorten:100 }}</p>
មេរៀន ១១

Lifecycle Hooks

Lifecycle Hooks ជា methods ពិសេសដែល Angular ហៅនៅ moment ជាក់លាក់ក្នុង lifecycle នៃ Component។

Lifecycle Hooks ទាំងអស់

Hookពេលណា?ប្រើសម្រាប់
ngOnChangesInput property ផ្លាស់ប្តូរreact to input changes
ngOnInitComponent init ហើយload data, setup
ngDoCheckការ detect changecustom change detection
ngAfterViewInitView init ហើយDOM manipulation
ngOnDestroyComponent destroycleanup, unsubscribe
TypeScript
import {
  Component, OnInit, OnDestroy, AfterViewInit,
  Input, OnChanges, SimpleChanges
} from '@angular/core';
import { Subscription } from 'rxjs';

@Component({ selector: 'app-example', template: '...' })
export class ExampleComponent implements OnInit, OnDestroy, AfterViewInit {
  @Input() userId!: number;
  private sub!: Subscription;

  ngOnChanges(changes: SimpleChanges) {
    console.log('Input ផ្លាស់ប្តូរ:', changes);
  }

  ngOnInit() {
    console.log('Component init!');
    // Load data, subscribe...
  }

  ngAfterViewInit() {
    console.log('View ready, DOM accessible!');
  }

  ngOnDestroy() {
    // ត្រូវ unsubscribe ដើម្បីការ memory leak
    this.sub?.unsubscribe();
  }
}
មេរៀន ១២

Modules & Lazy Loading

Module ជាការរៀបចំ code ជាក្រុមៗ។ Lazy Loading ជួយ load code ត្រឹមមានតម្រូវការ ដើម្បីលើកកម្ពស់ performance។

NgModule

TypeScript
@NgModule({
  declarations: [              // Components, Directives, Pipes
    AppComponent,
    HomeComponent,
  ],
  imports: [                   // Modules ផ្សេង
    BrowserModule,
    HttpClientModule,
    AppRoutingModule,
  ],
  providers: [ApiService],    // Services
  bootstrap: [AppComponent]  // Component ដំបូង
})

Feature Module

terminal
ng generate module admin --routing

Lazy Loading

TypeScript — app-routing.module.ts
const routes: Routes = [
  {
    path: 'admin',
    loadChildren: () =>
      import('./admin/admin.module')
        .then(m => m.AdminModule)
    // admin module ត្រូវ load ប្ រសិនបើ user ចូល /admin
  }
];
💡

Lazy Loading ជួយកាត់បន្ថយ initial bundle size ដែលធ្វើឱ្យ app load លឿន ជាពិសេសសម្រាប់ mobile!

មេរៀន ១៣

State Management ជាមួយ NgRx

NgRx គឺជា Redux-based State Management library សម្រាប់ Angular application ធំៗ។

NgRx ដំណើរការបែបណា?

🏗️

Component dispatch Action → Reducer update State → Store បង្ហាញ state ថ្មី → Component ទទួល។

Actions

TypeScript — counter.actions.ts
import { createAction, props } from '@ngrx/store';

export const increment = createAction('[Counter] Increment');
export const decrement = createAction('[Counter] Decrement');
export const reset = createAction('[Counter] Reset');
export const loadUsers = createAction('[Users] Load');
export const loadUsersSuccess = createAction(
  '[Users] Load Success',
  props<{ users: any[] }>()
);

Reducer

TypeScript — counter.reducer.ts
import { createReducer, on } from '@ngrx/store';

export const counterReducer = createReducer(
  0, // initial state
  on(increment, (state) => state + 1),
  on(decrement, (state) => state - 1),
  on(reset, () => 0)
);

Selector & Component

TypeScript
export class CounterComponent {
  count$ = this.store.select('counter');

  constructor(private store: Store<{ counter: number }>) {}

  onIncrement() { this.store.dispatch(increment()); }
  onDecrement() { this.store.dispatch(decrement()); }
  onReset() { this.store.dispatch(reset()); }
}
មេរៀន ១៤

Testing

Angular ប្រើ Jasmine + Karma សម្រាប់ Unit Test, និង Cypress/Protractor សម្រាប់ E2E Test។

Unit Test ជាមួយ Jasmine

TypeScript — counter.service.spec.ts
import { TestBed } from '@angular/core/testing';
import { CounterService } from './counter.service';

describe('CounterService', () => {
  let service: CounterService;

  beforeEach(() => {
    TestBed.configureTestingModule({});
    service = TestBed.inject(CounterService);
  });

  it('ត្រូវ increment counter', () => {
    service.increment();
    expect(service.count).toBe(1);
  });

  it('ត្រូវ reset ទៅ 0', () => {
    service.increment();
    service.reset();
    expect(service.count).toBe(0);
  });
});

Component Test

TypeScript
describe('AppComponent', () => {
  it('ត្រូវ render title', () => {
    const fixture = TestBed.createComponent(AppComponent);
    fixture.detectChanges();
    const compiled = fixture.nativeElement as HTMLElement;
    expect(compiled.querySelector('h1')?.textContent)
      .toContain('ស្វាគមន៍');
  });
});

Run Tests

terminal
# Unit tests
ng test

# E2E tests
ng e2e

# Coverage report
ng test --code-coverage
មេរៀន ១៥

Build & Deployment

រៀនពីរបៀប build app ដើម្បីយក​ production, optimize performance, និង deploy ទៅ server ផ្សេងៗ។

Build Production

terminal
# Production build
ng build --configuration=production

# output នៅ dist/my-app/

Performance Optimization

  • Lazy Loading — load modules ត្រឹមមានតម្រូវការ
  • OnPush Change Detection — ជៀសវាងការ check ដែលមិនចាំបាច់
  • Tree Shaking — Angular ដកចោល code ដែលមិនប្រើ
  • AOT Compilation — Compile ahead of time
TypeScript — OnPush
@Component({
  selector: 'app-item',
  template: '...',
  changeDetection: ChangeDetectionStrategy.OnPush
})

Deploy ទៅ Firebase Hosting

terminal
# Install Firebase CLI
npm install -g firebase-tools

# Login
firebase login

# Init project
firebase init hosting

# Build & Deploy
ng build --prod && firebase deploy

Deploy ទៅ Netlify / Vercel

terminal
# Netlify CLI
npm install -g netlify-cli
netlify deploy --dir=dist/my-app --prod

# Vercel
npm install -g vercel
vercel --prod
🎉

អបអរសាទរ! អ្នកបានបញ្ចប់ Angular Course ទាំង ១៥ មេរៀន! ត្រៀមខ្លួនសម្រាប់ professional Angular development ហើយ!