ngrx 入门---3、产品管理

本文档详细介绍了如何使用ngrx构建产品管理的基础,包括创建产品对象、数据源和产品仓库,接着逐步构建产品列表和编辑组件,修改路由及根组件的导航。最后,文章提到了运行项目的步骤,并提供了完整的代码参考链接。
摘要由CSDN通过智能技术生成

一、构建产品管理基础

1、构建产品对象 product.ts

ng g class example/model/product.model

修改product.model.ts为

export class Product {

    constructor(
        public id?: number,
        public name?: string,
        public category?: string,
        public description?: string,
        public price?: number
    ) { }
}

2、构建数据源

ng g class example/model/rest.datasource

rest.datasource.ts文件为

import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { Observable } from "rxjs";
import { Product } from "./product.model";

const PROTOCOL = "http";
const PORT = 3500;

@Injectable()
export class RestDataSource {
  baseUrl: string;
  auth_token: string;

  constructor(private http: HttpClient) {
    this.baseUrl = `${PROTOCOL}://${location.hostname}:${PORT}/`;
  }

  //获取全部产品数据
  getProducts(): Observable<Product[]> {
    return this.http.get<Product[]>(this.baseUrl + "products");
  }

  //保存产品数据
  saveProduct(product: Product): Observable<Product> {
    return this.http.post<Product>(this.baseUrl + "products",product);
  }

  //修改产品数据
  updateProduct(product): Observable<Product> {
    return this.http.put<Product>(this.baseUrl + "products", product);
  }
  //删除指定id的产品数据
  deleteProduct(id: number): Observable<Product> {
    return this.http.delete<Product>(`${this.baseUrl}products/${id}`);
  }
}

3、构建产品仓库

ng g class example/model/product.repository

修改product.repository.ts为

import { Injectable } from "@angular/core";
import { Product } from "./product.model";
import { RestDataSource } from "./rest.datasource";

@Injectable()
export class ProductRepository {
    private products: Product[]=[];
    private categories: string[]=[];

    constructor(private dataSource: RestDataSource) {
        dataSource.getProducts().subscribe(data => {
            this.products = data;
            this.categories = data.map(p => p.category)
                .filter((c, index, array) => array.indexOf(c) == index).sort() as string[];
        });
    }

    getProducts(category?: string): Product[] {
        return this.products
            .filter(p => category == null || category == p.category);
    }

    getProduct(id: number): Product {
        let product = this.products.find(p => p.id == id);
        return product;
    }

    getCategories(): string[] {
        return this.categories;
    }

    saveProduct(product: Product) {
        if (product.id == null || product.id == 0) {
            this.dataSource.saveProduct(product)
                .subscribe(p => this.products.push(p));
        } else {
            this.dataSource.updateProduct(product)
                .subscribe(() => {
                    this.products.splice(this.products.
                        findIndex(p => p.id == product.id), 1, product);
                });
        }
    }

    deleteProduct(id: number) {
        this.dataSource.deleteProduct(id).subscribe(p => {
            this.products.splice(this.products.
                findIndex(() => p.id == id), 1);
        })
    }
}

二、构建产品相关组件

1、构建产品列表组件

ng g c example/containers/product/productTable -m example

2、构建产品编辑组件

ng g c example/containers/product/productEditor -m example

3、修改example模块的路由

example-routing.module.ts

import { NgModule } from '@angular/core';
import { FormsModule } from "@angular/forms";
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';

import { ExampleRoutingModule } from './example-routing.module';
import { CounterComponent } from './containers/counter/counter.component';

import { StoreModule } from '@ngrx/store';
import { reducers } from './reducer';

import {RestDataSource} from './model/rest.datasource';
import {ProductRepository} from './model/product.repository';

import { ProductTableComponent } from './containers/product/product-table/product-table.component';
import { ProductEditorComponent } from './containers/product/product-editor/product-editor.component';


@NgModule({
  declarations: [CounterComponent, ProductTableComponent, ProductEditorComponent],
  imports: [
    FormsModule,
    CommonModule,
    HttpClientModule,      //必须引入,否则http无效
    ExampleRoutingModule,
    StoreModule.forFeature('example', reducers),  // 挂在在state上
  ],
  providers:[
    RestDataSource,ProductRepository
  ]
})
export class ExampleModule { }

4、修改根组件的html,增加导航

app.component.html

<div class="container-fluid">
  <div class="row">
    <div class="col bg-dark text-white">
      <a class="navbar-brand">ngrx入门</a>
    </div>
  </div>
  <div class="row mt-2">
    <div class="col-3">
      <button class="btn btn-outline-info btn-block" routerLink="/example/products" routerLinkActive="active">
        Products
      </button>
      <button class="btn btn-outline-info btn-block" routerLink="/example/counter" routerLinkActive="active">
        计算器
      </button>
    </div>
    <div class="col-9">
      <router-outlet></router-outlet>
    </div>
  </div>
</div>

5、修改产品列表

product-table.component.ts

import { Component, OnInit } from '@angular/core';
import { Product } from "src/app/example/model/product.model";
import { ProductRepository } from "src/app/example/model/product.repository";

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

  constructor(private repository: ProductRepository) {
  }

  ngOnInit(): void {
  }

  getProducts(): Product[] {
    return this.repository.getProducts();
  }

  deleteProduct(id: number) {
    this.repository.deleteProduct(id);
  }

}

product-table.component.html

<table class="table table-sm table-striped">
    <thead>
        <tr>
            <th>ID</th><th>Name</th><th>Category</th><th>Price</th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        <tr *ngFor="let p of getProducts()">
            <td>{{p.id}}</td>
            <td>{{p.name}}</td>
            <td>{{p.category}}</td>
            <td>{{p.price | currency:"USD":"symbol":"2.2-2"}}</td>
            <td>
                <button class="btn btn-sm btn-warning m-1"
                        [routerLink]="['/example/products/edit', p.id]">
                    Edit
                </button>
                <button class="btn btn-sm btn-danger" (click)="deleteProduct(p.id)">
                    Delete
                </button>
            </td>
        </tr>
    </tbody>
  </table>
  <button class="btn btn-primary" routerLink="/example/products/create">
    Create New Product
  </button>

6、修改产品编辑

product-editor.component.ts

import { Component, OnInit } from '@angular/core';
import { NgForm } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { Product } from 'src/app/example/model/product.model';
import { ProductRepository } from 'src/app/example/model/product.repository';

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

  editing: boolean = false;
  product: Product = new Product();

  constructor(private repository: ProductRepository,
    private router: Router,
    activeRoute: ActivatedRoute) {

    this.editing = activeRoute.snapshot.params["mode"] == "edit";
    if (this.editing) {
      Object.assign(this.product,
        repository.getProduct(activeRoute.snapshot.params["id"]));
      console.log("id = "+ activeRoute.snapshot.params["id"]);
      console.log(JSON.stringify(this.product));
    }
  }

  save(form: NgForm) {
    this.repository.saveProduct(this.product);
    this.router.navigateByUrl("/example/products");
  }

  ngOnInit(): void {
  }

}

product-editor.component.html

<div class="bg-primary p-2 text-white" [class.bg-warning]="editing"
     [class.text-dark]="editing">
    <h5>{{editing  ? "Edit" : "Create"}} Product</h5>
</div>
<form novalidate #form="ngForm" (ngSubmit)="save(form)">
    <div class="form-group">
        <label>Name</label>
        <input class="form-control" name="name" [(ngModel)]="product.name" />
    </div>
    <div class="form-group">
        <label>Category</label>
        <input class="form-control" name="category" [(ngModel)]="product.category" />
    </div>
    <div class="form-group">
        <label>Description</label>
        <textarea class="form-control" name="description"
                  [(ngModel)]="product.description">
        </textarea>
    </div>
    <div class="form-group">
        <label>Price</label>
        <input class="form-control" name="price" [(ngModel)]="product.price" />
    </div>
    <button type="submit" class="btn btn-primary m-1" [class.btn-warning]="editing">
        {{editing ? "Save" : "Create"}}
    </button>
    <button type="reset" class="btn btn-secondary" routerLink="/example/products">
        Cancel
    </button>
</form>

product-editor.component.css

input.ng-dirty.ng-invalid { border: 2px solid #ff0000 }
input.ng-dirty.ng-valid { border: 2px solid #6bc502 }

三、运行

完美,如计划一般的完美
代码参看:
https://gitee.com/lxhjh2015/ngrx/tree/step3/
或者
git clone -b step3 https://gitee.com/lxhjh2015/ngrx.git

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值