Angular គឺជាអ្វី?
Angular គឺជា Framework សម្រាប់បង្កើត Web Application ដែលត្រូវបានបង្កើតឡើងដោយ Google។ វាប្រើ TypeScript ជាភាសាសំខាន់ ហើយផ្តល់នូវ tools ពេញលេញដើម្បីបង្កើត application ធំៗ។
ពីចំនុចចាប់ផ្តើម រហូតដល់កម្រឹតខ្ពស់ · ភាសាខ្មែរ
មេរៀននេះនឹងបង្រៀនអ្នកអំពី Angular Framework ពីការចាប់ផ្តើមរហូតដល់កម្រឹតខ្ពស់ ជាភាសាខ្មែរ។
Angular គឺជា Framework សម្រាប់បង្កើត Web Application ដែលត្រូវបានបង្កើតឡើងដោយ Google។ វាប្រើ TypeScript ជាភាសាសំខាន់ ហើយផ្តល់នូវ tools ពេញលេញដើម្បីបង្កើត application ធំៗ។
រៀនពីរបៀបដំឡើង Node.js, Angular CLI, និងបង្កើត project ដំបូង។
| Tool | Version | ការប្រើប្រាស់ |
|---|---|---|
| Node.js | 18+ | JavaScript Runtime |
| npm | 9+ | Package Manager |
| Angular CLI | 17+ | Command Line Tool |
| VS Code | latest | Code Editor |
# ដំឡើង Angular CLI ជា global npm install -g @angular/cli # ពិនិត្យ version ng version
# បង្កើត project ng new my-first-app # ចូលទៅ folder cd my-first-app # run server ng serve --open
ពេល run ng serve, browser នឹងបើក http://localhost:4200 ដោយស្វ័យប្រវត្តិ។
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 គឺជាផ្នែកសំខាន់នៃ Angular Application។ រៀនពីរបៀបបង្កើត Component និងប្រើ Template។
Component គឺជា building block ដែលមានផ្ទុក:
# ប្រើ CLI បង្កើត component ng generate component hello # ឬ short form ng g c hello
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 = 'ខ្ញុំ'; }
<h1>{{ title }}</h1> <p>ហៅ {{ name }} ជំរាបសួរ!</p>
ដើម្បីប្រើ Component នៅក្នុង Component ផ្សេង ត្រូវដាក់ selector <app-hello></app-hello> ក្នុង HTML។
export class AppComponent { imageUrl: string = 'https://angular.io/assets/images/logos/angular/angular.png'; isDisabled: boolean = true; }
<img [src]="imageUrl" alt="Angular"> <button [disabled]="isDisabled">ចុច</button>
Data Binding ជាប្រព័ន្ធភ្ជាប់ data រវាង Component class និង Template (HTML)។
| ប្រភេទ | Syntax | ទិសដៅ |
|---|---|---|
| Interpolation | {{ value }} | Class → Template |
| Property Binding | [property]="value" | Class → Template |
| Event Binding | (event)="handler()" | Template → Class |
| Two-way Binding | [(ngModel)]="value" | ទាំងពីរ |
export class AppComponent { count: number = 0; increment() { this.count++; } onKeyPress(event: KeyboardEvent) { console.log('Key:', event.key); } }
<button (click)="increment()">ចុច: {{ count }}</button> <input (keyup)="onKeyPress($event)" placeholder="វាយអក្សរ...">
ត្រូវ import FormsModule ក្នុង app.module.ts ដើម្បីប្រើ ngModel។
import { FormsModule } from '@angular/forms'; @NgModule({ imports: [FormsModule], })
export class AppComponent { username: string = ''; }
<input [(ngModel)]="username" placeholder="ឈ្មោះ..."> <p>ស្វាគមន៍: {{ username }}</p>
Directives គឺជា instructions ដែលបន្ថែម behavior ទៅ HTML elements ឬ Component។
export class AppComponent { isLoggedIn: boolean = false; userRole: string = 'admin'; }
<div *ngIf="isLoggedIn"> ស្វាគមន៍! អ្នកបានចូល។ </div> <div *ngIf="!isLoggedIn; else loginBlock"> សូម Login ជាមុន </div> <ng-template #loginBlock> <p>អ្នកបានចូលហើយ!</p> </ng-template>
export class AppComponent { students = [ { id: 1, name: 'សុផា', score: 95 }, { id: 2, name: 'មករា', score: 87 }, { id: 3, name: 'ចន្ថា', score: 92 }, ]; }
<ul> <li *ngFor="let s of students; let i = index"> {{ i + 1 }}. {{ s.name }} — {{ s.score }} ពិន្ទុ </li> </ul>
<!-- ngClass --> <p [ngClass]="{ 'text-red': score < 50, 'text-green': score >= 50 }"> {{ score }} ពិន្ទុ </p> <!-- ngStyle --> <div [ngStyle]="{ 'color': isActive ? 'green' : 'red', 'font-size': '18px' }"> ស្ថានភាព </div>
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 ប្រើដើម្បីបែងចែក logic ចេញពី Component ដើម្បីឱ្យ code clean និង reusable។
Service គឺជា class ដែលផ្ទុក business logic, data, ឬ functionality ដែល Component ច្រើនអាចប្រើបាន។
ng generate service user
# ឬ
ng g s user
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); } }
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 អនុញ្ញាតឱ្យ user navigate រវាង page ផ្សេងៗក្នុង Single Page Application (SPA)។
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 {}
<nav> <a routerLink="/" routerLinkActive="active">ទំព័រដើម</a> <a routerLink="/about" routerLinkActive="active">អំពីយើង</a> </nav> <!-- Component នឹងបង្ហាញនៅទីនេះ --> <router-outlet></router-outlet>
const routes: Routes = [ { path: 'user/:id', component: UserDetailComponent } ];
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')!; } }
Angular ផ្តល់ Forms ពីរប្រភេទ: Template-Driven Forms និង Reactive Forms ដែលសម្រាប់ use case ផ្សេងៗ។
ងាយស្រួលប្រើ, អ្វីៗភាគច្រើននៅក្នុង HTML template។
<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>
ទំនាក់ទំនងច្រើនជាង, ប្រើ FormBuilder ក្នុង TypeScript code។
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); } } }
<form [formGroup]="form" (ngSubmit)="onSubmit()"> <input formControlName="name" placeholder="ឈ្មោះ"> <div *ngIf="form.get('name')?.invalid"> ឈ្មោះត្រូវការ (យ៉ាងហោចណាស់ 3 អក្សរ) </div> <button type="submit">ចុះឈ្មោះ</button> </form>
Angular ប្រើ HttpClient Module ដើម្បីទំនាក់ទំនងជាមួយ REST API Server។
import { HttpClientModule } from '@angular/common/http'; @NgModule({ imports: [HttpClientModule] })
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}`); } }
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 គឺជា library សម្រាប់ Reactive Programming ដោយប្រើ Observable streams។ Angular ប្រើ RxJS ខ្លាំងណាស់។
| Observable | Promise |
|---|---|
| Lazy (ដំណើរការនៅពេល subscribe) | Eager (ដំណើរការភ្លាម) |
| បង្ហាញ value ច្រើនដង | បង្ហាញ value តែម្តង |
| អាច cancel បាន | Cancel មិនបាន |
| មាន operators ច្រើន | operators តិច |
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 ក្នុង template ដើម្បីដំណើរការ Observable ដោយស្វ័យប្រវត្តិ ដោយមិនចាំបាច់ subscribe ដោយខ្លួនឯង។
export class AppComponent { posts$ = this.api.getPosts(); // Observable, មិន subscribe constructor(private api: ApiService) {} }
<div *ngFor="let post of posts$ | async"> {{ post.title }} </div>
Pipes ប្រើដើម្បីបំប្លែង data ក្នុង template ក្នុងទម្រង់ដែលចង់ = formatting tools ។
<!-- 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>
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) + '...'; } }
<p>{{ longText | shorten:100 }}</p>
Lifecycle Hooks ជា methods ពិសេសដែល Angular ហៅនៅ moment ជាក់លាក់ក្នុង lifecycle នៃ Component។
| Hook | ពេលណា? | ប្រើសម្រាប់ |
|---|---|---|
ngOnChanges | Input property ផ្លាស់ប្តូរ | react to input changes |
ngOnInit | Component init ហើយ | load data, setup |
ngDoCheck | ការ detect change | custom change detection |
ngAfterViewInit | View init ហើយ | DOM manipulation |
ngOnDestroy | Component destroy | cleanup, unsubscribe |
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(); } }
Module ជាការរៀបចំ code ជាក្រុមៗ។ Lazy Loading ជួយ load code ត្រឹមមានតម្រូវការ ដើម្បីលើកកម្ពស់ performance។
@NgModule({ declarations: [ // Components, Directives, Pipes AppComponent, HomeComponent, ], imports: [ // Modules ផ្សេង BrowserModule, HttpClientModule, AppRoutingModule, ], providers: [ApiService], // Services bootstrap: [AppComponent] // Component ដំបូង })
ng generate module admin --routing
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!
NgRx គឺជា Redux-based State Management library សម្រាប់ Angular application ធំៗ។
Component dispatch Action → Reducer update State → Store បង្ហាញ state ថ្មី → Component ទទួល។
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[] }>() );
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) );
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()); } }
Angular ប្រើ Jasmine + Karma សម្រាប់ Unit Test, និង Cypress/Protractor សម្រាប់ E2E Test។
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); }); });
describe('AppComponent', () => { it('ត្រូវ render title', () => { const fixture = TestBed.createComponent(AppComponent); fixture.detectChanges(); const compiled = fixture.nativeElement as HTMLElement; expect(compiled.querySelector('h1')?.textContent) .toContain('ស្វាគមន៍'); }); });
# Unit tests ng test # E2E tests ng e2e # Coverage report ng test --code-coverage
រៀនពីរបៀប build app ដើម្បីយក production, optimize performance, និង deploy ទៅ server ផ្សេងៗ។
# Production build ng build --configuration=production # output នៅ dist/my-app/
@Component({ selector: 'app-item', template: '...', changeDetection: ChangeDetectionStrategy.OnPush })
# Install Firebase CLI npm install -g firebase-tools # Login firebase login # Init project firebase init hosting # Build & Deploy ng build --prod && firebase deploy
# 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 ហើយ!