ABP-Book Store Application中文讲解 - Part 3: Creating, Updating and Deleting Books

ABP-Book Store Application中文讲解 - Part 3: Creating, Updating and Deleting Books。

本章用于介绍如何新增、编辑和删除Book。

 1. 汇总

ABP-Book Store Application中文讲解-汇总-CSDN博客

2. 前一章 

ABP-Book Store Application中文讲解 - Part 2: The Book List Page

项目之间的引用关系。

目录

1. Create a New Book

1.1 方法一:单独创建dialog component

1.1.1 更改add-edit-book.component.html 

1.1.2 更改add-edit-book.component.ts (即AddEditBookComponent)

 1.1.3 book.module.ts添加引用

1.1.4 book.component.html增加新增,删除和编辑

1.1.5 book.component.ts中使用AddEditBookComponent

1.2 方法二:将所有业务逻辑放在BookComponent

2. 继续学习


1. Create a New Book

创建 新增Book的窗体。

此处可以有两种方式:

第一种是单独创建一个component,比如add-edit-book,然后在里面实现所有的业务逻辑,保存和关闭按钮可以通过NgbModal用来显示和关闭dialog。本文重点介绍这一个方法。

第二种是将所有业务逻辑放在BookComponent里面实现,即ABP官方Demo给出的完整代码。

1.1 方法一:单独创建dialog component

右击book文件夹,选择Open in integrated Terminal, 然后输入以下命令敲回车生成AddEditBookComponent。

ng generate component add-edit-book

创建完成,目录结构如下图所示: 

1.1.1 更改add-edit-book.component.html 

<form [formGroup]="form" (ngSubmit)="save()">
    <div class="modal-header">
        <h4 class="modal-title">
            {{ (book && book.id ? '::EditBook' : '::NewBook') | abpLocalization }}
        </h4>
        <button type="button" class="btn-close" aria-label="Close" (click)="activeModal.dismiss()"></button>
    </div>
    <div class="modal-body">
        <div class="formGroup mt-2">
            <label for="book-name">{{'::Name' | abpLocalization}}</label><span> * </span>
            <input type="text" id="book-name" class="form-control" formControlName="name" autofocus />
        </div>

        <div class="formGroup mt-2">
            <label for="book-price">{{'::Price' | abpLocalization}}</label><span> * </span>
            <input type="number" id="book-price" class="form-control" formControlName="price" formControlName="price" />
        </div>

        <div class="formGroup mt-2">
            <label for="book-type">{{'::Type' | abpLocalization}}</label><span> * </span>
            <select class="form-control" id="book-type" formControlName="type">
                <option [ngValue]="null">Select a book type</option>
                <option [ngValue]="type.value" *ngFor="let type of bookTypes"> {{ '::Enum:BookType.' + type.value |
                    abpLocalization }}</option>
            </select>
        </div>

        <div class="formGroup mt-2">
            <label>{{'::PublishDate' | abpLocalization}}</label><span> * </span>
            <input #datepicker="ngbDatepicker" class="form-control" name="datepicker" formControlName="publishDate"
                ngbDatepicker (click)="datepicker.toggle()" />
        </div>
    </div>
    <div class="modal-footer">
        <button class="btn btn-secondary" type="button" (click)="activeModal.dismiss()">{{'::Cancel' |
            abpLocalization}}</button>
        <button class="btn btn-primary" type="submit" [disabled]="form.invalid">
            {{ (book && book.id ? '::Update' :'::Save') | abpLocalization }}
        </button>
    </div>
</form>

1.1.2 更改add-edit-book.component.ts (即AddEditBookComponent)

注意此处更改了standalone,改为了false

然后引用都需要在book.module.ts中添加对应的引用,具体参看book.module.ts

import { Component, OnInit } from '@angular/core';
import { BookService, BookDto, CreateUpdateBookDto, bookTypeOptions } from '../../proxy/books';  // Import your BookService and BookDto model
import { FormGroup, FormBuilder, Validators } from '@angular/forms';

import { NgbDateNativeAdapter, NgbDateAdapter } from '@ng-bootstrap/ng-bootstrap';// added this line
import { ListService } from '@abp/ng.core';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
// added this line

@Component({
  selector: 'app-add-edit-book',
  templateUrl: './add-edit-book.component.html',
  styleUrl: './add-edit-book.component.scss',
  standalone: false, // 标记为独立组件
  providers: [
    ListService,
    { provide: NgbDateAdapter, useClass: NgbDateNativeAdapter } // add this line
  ],
})
export class AddEditBookComponent implements OnInit {
  public book: BookDto = {} as BookDto;  // Input property to receive book data from parent component
  form: FormGroup;

  bookTypes = bookTypeOptions;

  constructor(private bookService: BookService
    , private fb: FormBuilder
    , public activeModal: NgbActiveModal) { this.buildForm(); }  // Inject BookService for adding or updating bo  oks


  ngOnInit(): void {
    this.buildForm();
  }

  // add buildForm method
  buildForm() {
    this.form = this.fb.group({
      name: [this.book.name, Validators.required],
      type: [this.book.type, Validators.required],
      publishDate: [this.book.publishDate ? new Date(this.book.publishDate) : null, Validators.required],
      price: [this.book.price, Validators.required],
    });
  }

  save() {  // Method to save or update a book
    if (this.form.invalid) {  // Check if the form is invalid
      return;  // Exit the method if the form is invalid
    }
    const operation$ = this.book.id
      ? this.bookService.update(this.book.id, this.form.value)
      : this.bookService.create(this.form.value);

    operation$.subscribe(() => {
      this.form.reset();// reset form values
      this.activeModal.close(true);// true used to inform the parent component that the book has been saved/updated
    });
  }
}

 1.1.3 book.module.ts添加引用

完整代码 

import { NgModule } from '@angular/core';
import { SharedModule } from '../shared/shared.module';
import { BookRoutingModule } from './book-routing.module';
import { NgbDatepickerModule } from '@ng-bootstrap/ng-bootstrap'; // add this line
import { FormsModule } from '@angular/forms';
import { NgbDateNativeAdapter, NgbDateAdapter } from '@ng-bootstrap/ng-bootstrap';// added this line
import { ListService } from '@abp/ng.core';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { AddEditBookComponent } from './add-edit-book/add-edit-book.component';// add this line

@NgModule({
  declarations: [
    AddEditBookComponent // Import AddEditBookComponent to make it available in this module
  ],
  imports: [
    BookRoutingModule,
    SharedModule// shared module already export CommonModule, so we don't need to import it again.
    , NgbDatepickerModule // add this line
    ,FormsModule
  ],
  providers: [ListService, NgbActiveModal, // Provide ListService and NgbActiveModal for this module
    { provide: NgbDateAdapter, useClass: NgbDateNativeAdapter } // add this line to use native date adapter
  ],
})
export class BookModule { }

1.1.4 book.component.html增加新增,删除和编辑

新增按钮

编辑和删除按钮

完整代码

<div class="card">
    <div class="card-header">
        <div class="row">
            <div class="col col-md-6">
                <h5 class="card-title">
                    {{'::Menu:Books' | abpLocalization}}
                </h5>
            </div>
            <div class="col col-md-6 text-lg-end pt-2">
                <button class="btn btn-primary" (click)="createBook()">
                    <i class="fa fa-plus me-1"></i>
                    {{'::NewBook' | abpLocalization}}
                </button>
            </div>
        </div>
    </div>
    <div class="card-body">
        <ngx-datatable [rows]="book.items" [count]="book.totalCount" [list]="list" default>
            <ngx-datatable-column name="{{'::Name' | abpLocalization}}" prop="name"></ngx-datatable-column>
            <ngx-datatable-column name="{{'::Type' | abpLocalization}}" prop="type">
                <ng-template let-column="column" let-row="row" ngx-datatable-cell-template>
                    {{'::Enum:BookType.' + row.type | abpLocalization}}
                </ng-template>
            </ngx-datatable-column>
            <ngx-datatable-column name="{{'::Price' | abpLocalization}}" prop="price">
                <ng-template let-column="column" let-row="row" ngx-datatable-cell-template>
                    <!-- {{row.price | currency:'USD':true}} -->
                    {{row.price | currency}}
                </ng-template>
            </ngx-datatable-column>
            <ngx-datatable-column name="{{'::PublishDate' | abpLocalization}}" prop="publishDate">
                <ng-template let-column="column" let-row="row" ngx-datatable-cell-template>
                    <!-- {{row.publishDate | date:'dd/MM/yyyy'}} -->
                    {{row.publishDate | date}}
                </ng-template>
            </ngx-datatable-column>
            <ngx-datatable-column [name]="'::Actions' | abpLocalization" [maxWidth]="150" [sortable]="false">
                <ng-template let-row="row" ngx-datatable-cell-template>
                    <div ngbDropdown container="body" class="d-inline-block">
                        <button class="btn btn-primary btn-sm dropdown-toggle" data-toggle="dropdown"
                            aria-haspopup="true" ngbDropdownToggle>
                            <i class="fa fa-cog me-1"></i>{{ '::Actions' | abpLocalization }}
                        </button>
                        <div ngbDropdownMenu>
                            <button ngbDropdownItem (click)="editBook(row.id)">
                                {{ '::Edit' | abpLocalization }}
                            </button>
                            <!-- add the Delete button -->
                            <button ngbDropdownItem (click)="delete(row.id)">
                                {{ '::Delete' | abpLocalization }}
                            </button>
                        </div>
                    </div>
                </ng-template>
            </ngx-datatable-column>
        </ngx-datatable>
    </div>
</div>

1.1.5 book.component.ts中使用AddEditBookComponent

引用

import { ConfirmationService, Confirmation } from '@abp/ng.theme.shared';
import { AddEditBookComponent } from './add-edit-book/add-edit-book.component';

在ctor中添加ConfirmationService和NgbModal

 private confirmationService: ConfirmationService, private modalService: NgbModal

  constructor(private bookService: BookService, public readonly list: ListService, private confirmationService: ConfirmationService, private modalService: NgbModal) { }  // Inject BookService and ListService

新增-利用NgbModal


  createBook() {
    const modalRef = this.modalService.open(AddEditBookComponent, { size: 'lg' });
    modalRef.componentInstance.book = {} as BookDto; // Pass an empty BookDto to the modal
    modalRef.result.then((result) => {
      if (result) {
        this.list.get();
      }
    });
  }

 编辑-利用NgbModal

  // Add editBook method
  editBook(id: string) {
    this.bookService.get(id).subscribe((book) => {
      this.selectedBook = book;
      const modalRef = this.modalService.open(AddEditBookComponent, { size: 'lg' });
      modalRef.componentInstance.book = book;
      modalRef.result.then((result) => {
        if (result) {
          this.list.get();
        }
      });
    });
  }

删除-利用confirmationService

  // Add a delete method
  delete(id: string) {
    this.confirmationService.warn('::AreYouSureToDelete', '::AreYouSure').subscribe((status) => {
      if (status === Confirmation.Status.confirm) {
        this.bookService.delete(id).subscribe(() => this.list.get());
      }
    });
  }

 完整代码

import { Component, OnInit } from '@angular/core';
import { ListService, PagedResultDto } from '@abp/ng.core';  // Import ListService and PagedResultDto
import { BookService, BookDto } from '../proxy/books';  // Import your BookService and BookDto model
import { SharedModule } from '../shared/shared.module';
import { ConfirmationService, Confirmation } from '@abp/ng.theme.shared';
import { AddEditBookComponent } from './add-edit-book/add-edit-book.component';

import { NgbModal } from '@ng-bootstrap/ng-bootstrap';

@Component({
  selector: 'app-book',
  templateUrl: './book.component.html',
  styleUrl: './book.component.scss',
  standalone: true, // 标记为独立组件
  imports: [SharedModule], // standalone: true导入需要的模块
  providers: [ListService],  // Provide ListService for this component
})
export class BookComponent implements OnInit {
  book = { items: [], totalCount: 0 } as PagedResultDto<BookDto>;  // Initialize books as an empty PagedResultDto
  selectedBook = {} as BookDto; // declare selectedBook

  constructor(private bookService: BookService, public readonly list: ListService, private confirmationService: ConfirmationService, private modalService: NgbModal) { }  // Inject BookService and ListService

  ngOnInit() {  // Use ngOnInit to fetch books when the component initializes
    this.list.hookToQuery(this.bookService.getList).subscribe((response) => {  // Hook to the query and subscribe to the response
      this.book = response;  // Assign the response to books
    });
  }

  createBook() {
    const modalRef = this.modalService.open(AddEditBookComponent, { size: 'lg' });
    modalRef.componentInstance.book = {} as BookDto; // Pass an empty BookDto to the modal
    modalRef.result.then((result) => {
      if (result) {
        this.list.get();
      }
    });
  }

  // Add editBook method
  editBook(id: string) {
    this.bookService.get(id).subscribe((book) => {
      this.selectedBook = book;
      const modalRef = this.modalService.open(AddEditBookComponent, { size: 'lg' });
      modalRef.componentInstance.book = book;
      modalRef.result.then((result) => {
        if (result) {
          this.list.get();
        }
      });
    });
  }
  // Add a delete method
  delete(id: string) {
    this.confirmationService.warn('::AreYouSureToDelete', '::AreYouSure').subscribe((status) => {
      if (status === Confirmation.Status.confirm) {
        this.bookService.delete(id).subscribe(() => this.list.get());
      }
    });
  }
}

1.2 方法二:将所有业务逻辑放在BookComponent

具体参考ABP.IO官网例子:

Web Application Development Tutorial - Part 3: Creating, Updating and Deleting Books | ABP.IO Documentation

2. 继续学习

ABP-Book Store Application中文讲解 - Part 4: Integration Tests

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值