Thuta Learning
ရှာဖွေရန်
ProjectsWeb Developmentintermediate

Mini Project: Task Tracker (Part 3 - Polish & Wrap-up)

စိတ်လျှော့ပါ။ ဒီခန်းကို စာအုပ်လိုမဟုတ်ဘဲ စကားပြောသလိုပဲ၊ နားလည်လွယ်အောင် ရှင်းပါမယ်။

ဒီခန်းပြီးရင် ဘာတတ်သွားမလဲ

  • Mini Project: Task Tracker (Part 3 - Polish & Wrap-up) ကို လက်တွေ့ project ထဲမှာ အသုံးချတတ်မယ်
  • ကိုယ်တိုင် code ရေးပြီး run ကြည့်တတ်မယ်
  • Project တစ်ခုလုံးကို အဆင့်လိုက် ဆောက်တတ်မယ်

ခဏလေး ဒီလိုပဲ စဉ်းစားကြည့်

Part 3 ဟာ project ရဲ့ နောက်ဆုံးအဆင့်ဖြစ်ပြီး core feature တွေ ပြီးသွားတဲ့နောက်မှာ user experience နဲ့ code quality ကို မြှင့်တင်တဲ့ polish တွေ ထည့်သွားမှာပါ။ Custom pipe, async pipe, form validation နဲ့ route guard lesson တွေက ဒီအဆင့်အတွက် တိုက်ရိုက်အသုံးဝင်ပါတယ်။ Task count summary ကို custom pipe နဲ့ format လုပ်ခြင်း၊ template ထဲမှာ subscribe/unsubscribe လက်ဖြစ်တာကို ရှောင်ဖို့ async pipe ပြောင်းသုံးခြင်း၊ title field empty မဖြစ်အောင် validation ထည့်ခြင်းနဲ့ task ID မတွေ့ရင် detail page ကို ဝင်လို့မရအောင် guard ထားခြင်းတို့ဖြင့် app ကို ပြီးပြည့်စုံအောင် ဆောင်ရွက်သွားမှာပါ။

လက်တွေ့ ဆောက်ကြည့်မယ်

`TaskCountPipe` ဆိုတဲ့ custom pipe တစ်ခုဆောက်ပြီး "3/5 completed" ပုံစံ text ပြန်ပေးအောင် transform() ရေးပါ။ TaskListComponent template ထဲမှာ tasks$ Observable ကို `| async` pipe နဲ့ တိုက်ရိုက် bind လုပ်ပြီး manual subscribe() ကို ဖယ်ရှားပါ။ Task form ရဲ့ title field ကို Validators.required ထည့်ပြီး invalid ဖြစ်ရင် submit button disable ဖြစ်အောင် လုပ်ပါ။ `taskExistsGuard` CanActivate guard တစ်ခု ဆောက်ပြီး TaskDetailComponent route မှာ id parameter နဲ့ task ရှိမရှိစစ်ပြီး မရှိရင် root path ကို redirect ပြန်ပို့ပါ။ နောက်ဆုံး README.md တစ်ခု ရေးပြီး project ကို summarize ပါ။

Code နမူနာ

typescript
// task-count.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
import { Task } from './task.model';

@Pipe({ name: 'taskCount' })
export class TaskCountPipe implements PipeTransform {
  transform(tasks: Task[]): string {
    const completed = tasks.filter(t => t.completed).length;
    return `${completed}/${tasks.length} completed`;
  }
}

// task-exists.guard.ts
import { inject } from '@angular/core';
import { CanActivateFn, Router } from '@angular/router';
import { TaskService } from './task.service';
import { map, take } from 'rxjs/operators';

export const taskExistsGuard: CanActivateFn = (route) => {
  const taskService = inject(TaskService);
  const router = inject(Router);
  const id = Number(route.paramMap.get('id'));

  return taskService.tasks$.pipe(
    take(1),
    map(tasks => {
      const found = tasks.some(t => t.id === id);
      return found ? true : router.parseUrl('/');
    })
  );
};
You should see
App ကို ပြန်ဖွင့်တဲ့အခါ list ပေါ်မှာ completed count summary ပေါ်နေပြီး title မထည့်ဘဲ submit လုပ်လို့မရဘဲ၊ မရှိတဲ့ task id ကို URL ကနေ တိုက်ရိုက်ဝင်ကြည့်ရင် root page ကို redirect ပြန်ဖြစ်သွားမှာဖြစ်သည်။

၅ မိနစ် စမ်းကြည့်

5 minutes အတွင်း TaskCountPipe ကို pure: false မလုပ်ဘဲ default pure pipe အနေနဲ့ ထားပြီး immutable array update လုပ်ရင်လည်း correctly update ဖြစ်မဖြစ် စမ်းသပ်ကြည့်ပါ။

သတိလေးတစ်ချက်

Custom pipe တွေကို default (pure) အနေနဲ့ ထားခြင်းက performance အတွက် ကောင်းသော်လည်း array ကို mutate လုပ်ရင် change မမှတ်တတ်တာကို သတိထားပါ — immutable update pattern အမြဲသုံးပါ။

ဒီနေရာမှာ လူအများမှားတတ်တယ်

  • async pipe သုံးထားရင်း manual subscribe() ကိုပါ ထပ်ထားမိပြီး subscription ကွဲနှစ်ခု run ဖြစ်တတ်သည်
  • Guard ကို routes array ထဲက canActivate property မှာ ချိတ်ဖို့ မေ့တတ်ကြသည်

အခု ကိုယ်တိုင် စမ်းကြည့်

5 minutes အတွင်း TaskCountPipe ကို pure: false မလုပ်ဘဲ default pure pipe အနေနဲ့ ထားပြီး immutable array update လုပ်ရင်လည်း correctly update ဖြစ်မဖြစ် စမ်းသပ်ကြည့်ပါ။

You'll know it worked when: App ကို ပြန်ဖွင့်တဲ့အခါ list ပေါ်မှာ completed count summary ပေါ်နေပြီး title မထည့်ဘဲ submit လုပ်လို့မရဘဲ၊ မရှိတဲ့ task id ကို URL ကနေ တိုက်ရိုက်ဝင်ကြည့်ရင် root page ကို redirect ပြန်ဖြစ်သွားမှာဖြစ်သည်။

Mini Project: Task Tracker (Part 3 - Polish & Wrap-up) | Thuta Learning