วันจันทร์ที่ 6 มกราคม พ.ศ. 2563

Angular 8 - แบ่ง Component เป็นหน้า ๆ กับ Router Module

ความเดิมจากตอนที่แล้วเราได้ทำการ Follow Guide หัวข้อ Your First App เสร็จแล้ว https://angular.io/start
ให้หัวข้อต่อมาเรื่องของ Routing https://angular.io/start/routing จะเริ่มสร้างหน้าย่อ ๆ กัน

ใช้ Code ต่อจากตอนที่แล้วเราจะทำการเพิ่ม RouterModule อย่างเดียวแล้วทำความเข้าใจกันก่อนว่ามันเป็นส่วนไหน
ให้เราทำการ Import Module ชื่อ "RouterModule" และทำการ Import และใส่ข้อมูล Path ด้วยใน "RouterModule.forRoot([])"
ส่วนของ path ใช่เป็น ' ' หมายถึง Root และแสดง Component ProductListComponent
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

import { RouterModule } from '@angular/router';

import { TopBarComponent } from './top-bar/top-bar.component';
import { ProductListComponent } from './product-list/product-list.component';
import { ProductAlertsComponent } from './product-alerts/product-alerts.component';


@NgModule({
  declarations: [
    AppComponent,
    TopBarComponent,
    ProductListComponent,
    ProductAlertsComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    RouterModule.forRoot([
      { path: '', component: ProductListComponent }
    ]),
  ],
  providers: [],
  bootstrap: [AppComponent]
})

export class AppModule { }
<app-top-bar></app-top-bar>
<app-product-list></app-product-list>

<router-outlet></router-outlet>

เมื่อ Run App เราจะเห็นว่ามี Product List 2 อันเรียกกันอยู่

อธิบาย
ไฟล์ "app.component.html" เป็นหน้าหลักที่ใช้ในการแสดงและ Tag "router-outlet" นั้นได้เอา ProductListComponent ขึ้นมาแสดงทำให้ซ้อนกัน
กับที่เราเพิ่ม Tag "app-product-list" ก่อนหน้านี้

ให้เราทำการลบ Tag "app-product-list" ออกแล้วกลับไปดูที่ App อีกครั้ง
<app-top-bar></app-top-bar>
<!-- ลบส่วนที่ Comment นี้ -->
<!--app-product-list></app-product-list-->

<router-outlet></router-outlet>



เราจะทำการสร้างหน้า ProductDetail ตาม Guide Routing โดนเราจะสร้าง Component ProductDetail แล้วทดสอบ Link ไปว่าทำงานได้ไหม

สร้าง Component ชื่อ ProductDetail ผ่านคำสั่ง ng แบบนี้ "ng generate component product-detail"
แล้วแก้ไข RouterModule ทำการเพิ่ม path ไปยัง "product-detail" และแก้ไข ProductList โดยเมื่อกดที่ชื่อมือถือให้ไปยังหน้า ProductDetail
ใช้ [routerLink]="['path']" | อ่านเพิ่มเติมได้ที่ https://angular.io/api/router/RouterLink
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

import { RouterModule } from '@angular/router';

import { TopBarComponent } from './top-bar/top-bar.component';
import { ProductListComponent } from './product-list/product-list.component';
import { ProductAlertsComponent } from './product-alerts/product-alerts.component';


@NgModule({
  declarations: [
    AppComponent,
    TopBarComponent,
    ProductListComponent,
    ProductAlertsComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    RouterModule.forRoot([
      { path: '', component: ProductListComponent },
      { path: 'product', component: ProductDetailComponent }
    ]),
  ],
  providers: [],
  bootstrap: [AppComponent]
})

export class AppModule { }
<h1>{{title}}</h1>

<div *ngFor="let product of productList">
    <a [title]="'Description: ' + product.description" [routerLink]="['/product']">
        {{product.name}}
    </a>

    <p *ngIf="product.description">
        {{product.description}}
    </p>

    <button (click)="share()">
        Share
    </button>

    <app-product-alerts [product]="product" (notify)="onNotify()"></app-product-alerts>

</div>

ทำการทดสอบโดยการคลิกที่ Link ชื่อมือถือจะส่งไปยังหน้า ProductDetail



การส่งค่าไปพร้อมกับ Link ด้วย ให้เราทำการแก้ไขส่วนของ RouterModule ส่วนของ path ให้เพิ่ม /:productId เพื่อบอกว่าจะรับ Product Id ต่อจาก /
และทำการแก้ไขส่วนของ ProductList เพิ่มส่วนของ RouterLink ให้เพิ่ม productId มาด้วย
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

import { RouterModule } from '@angular/router';

import { TopBarComponent } from './top-bar/top-bar.component';
import { ProductListComponent } from './product-list/product-list.component';
import { ProductAlertsComponent } from './product-alerts/product-alerts.component';


@NgModule({
  declarations: [
    AppComponent,
    TopBarComponent,
    ProductListComponent,
    ProductAlertsComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    RouterModule.forRoot([
      { path: '', component: ProductListComponent },
      { path: 'product/:productId', component: ProductDetailComponent }
    ]),
  ],
  providers: [],
  bootstrap: [AppComponent]
})

export class AppModule { }
<h1>{{title}}</h1>

<div *ngFor="let product of productList; index as productId">
    <a [title]="'Description: ' + product.description" [routerLink]="['/product', productId]">
        {{product.name}}
    </a>

    <p *ngIf="product.description">
        {{product.description}}
    </p>

    <button (click)="share()">
        Share
    </button>

    <app-product-alerts [product]="product" (notify)="onNotify()"></app-product-alerts>

</div>
สังเกตุที่ URL จะมี ProductId ติดมาด้วย


การรับค่าไปใช้งานต่อใน ProductDetail เราจะใช้ https://angular.io/guide/lifecycle-hooks
ทำการเพิ่ม Code ในส่วนของ ngOnInit() {} โดยเรียก this.route.paramMap.subscribe(params => {})
ก่อนเรียกใช้งาน route ให้ทำการ Import ActivatedRoute [บรรทัดที่ 2] และรับ route ที่ Contructor [บรรทัดที่ 11] ด้วย

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Component({
  selector: 'app-product-detail',
  templateUrl: './product-detail.component.html',
  styleUrls: ['./product-detail.component.css']
})
export class ProductDetailComponent implements OnInit {

  constructor(private route: ActivatedRoute) { }

  ngOnInit() {

    this.route.paramMap.subscribe(params => {
      window.alert(params.get('productId'));
    });

  }

}



การดึงค่าออกมาแสดง โดยให้ทำการ Import products [บรรทัดที่ 4] เข้ามาก่อนจากนั้นเอา productId ไปเลือกว่าเป็น Product ตัวไหน [บรรทัดที่ 21]
แล้วกำหนดค่าให้กับ product ที่อยู่ใน ProductDetail และทำออกมาแสดงที่ Template
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

import { products } from '../products';

@Component({
  selector: 'app-product-detail',
  templateUrl: './product-detail.component.html',
  styleUrls: ['./product-detail.component.css']
})
export class ProductDetailComponent implements OnInit {

  product;

  constructor(private route: ActivatedRoute) { }

  ngOnInit() {

    this.route.paramMap.subscribe(params => {
      // window.alert(params.get('productId'));
      this.product = products[+params.get('productId')];
    });

  }

}
<h2>Product Details</h2>

<div *ngIf="product">
  <h3>{{ product.name }}</h3>
  <h4>{{ product.price | currency }}</h4>
  <p>{{ product.description }}</p>

</div>
จบแล้ว

ไม่มีความคิดเห็น:

แสดงความคิดเห็น