CRUD и маршрутизация. Часть 2

Последнее обновление: 18.02.2020

Продолжим работу с проектом из прошлой темы. И теперь в папке ClientApp/src/app определим файл product-form.component.ts:

import { Component, Input } from '@angular/core';
import { Product } from './product';
@Component({
    selector: "product-form",
    templateUrl: './product-form.component.html'
})
export class ProductFormComponent {
    @Input() product: Product;
}

Этот компонент будет представлять форму (добавления или редактирования), данные которой будет представлять объект Product. Сам объект Product будет передаваться компоненту из вне. Поэтому к переменной компонента, которая будет хранить добавляемый или редактируемый объект Product, применяется декоратор @Input.

Этот компонент будет использовать файл product-form.component.html, который определяет форму для ввода значений объекта Product. Поэтому добавим данный файл в папку ClientApp/src/app и определим в нем следующий код:

<div class="form-group">
    <label>Модель</label>
    <input type="text" [(ngModel)]="product.name" class="form-control" />
</div>
<div class="form-group">
    <label>Производитель</label>
    <input type="text" [(ngModel)]="product.company" class="form-control" />
</div>
<div class="form-group">
    <label>Цена</label>
    <input type="number" [(ngModel)]="product.price" class="form-control" />
</div>

Этот компонент будет использоваться при добавлении и редактировании. И теперь добавим в папку ClientApp/src/app новый файл product-create.component.ts, который будет хранит компонент добавления нового объекта:

import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { DataService } from './data.service';
import { Product } from './product';

@Component({
    templateUrl: './product-create.component.html'
})
export class ProductCreateComponent {

    product: Product = new Product();    // добавляемый объект
    constructor(private dataService: DataService, private router: Router) { }
    save() {
        this.dataService.createProduct(this.product).subscribe(data => this.router.navigateByUrl("/"));
    }
}

Этот компонент добавляет новый объект Product. Добавление производится в методе save с помощью метода createProduct у сервиса DataService. После добавления с помощью метода router.navigateByUrl() производится программный переход на корень приложения.

И также добавим в папку ClientApp/src/app файл product-create.component.html, который будет использоваться этим компонентом:

<div>
    <h2>Добавление нового товара</h2>
    <product-form [(product)]="product"></product-form>
    <div class="form-group">
        <input type="button" value="Сохранить" (click)="save()" class="btn btn-success" />
        <a routerLink="/" class="btn btn-warning">Отмена</a>
    </div>
</div>

Для определения формы здесь применяется компонент ProductFormComponent, а для сохранения объекта при нажатии на кнопку будет вызываться метод save.

Далее добавим в каталог ClientApp/src/app новый файл product-edit.component.ts, который будет представлять компонент редактирования объекта:

import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { DataService } from './data.service';
import { Product } from './product';

@Component({
    templateUrl: './product-edit.component.html'
})
export class ProductEditComponent implements OnInit {

    id: number;
    product: Product;    // изменяемый объект
    loaded: boolean = false;

    constructor(private dataService: DataService, private router: Router, activeRoute: ActivatedRoute) {
        this.id = Number.parseInt(activeRoute.snapshot.params["id"]);
    }

    ngOnInit() {
        if (this.id)
            this.dataService.getProduct(this.id)
                .subscribe((data: Product) => {
                    this.product = data;
                    if (this.product != null) this.loaded = true;
                });
    }

    save() {
        this.dataService.updateProduct(this.product).subscribe(data => this.router.navigateByUrl("/"));
    }
}

Этот компонент с помощью системы маршрутизации будет получать id редактируемого объекта и вызывать у сервиса метод getProduct() для получения этого объекта.

С помощью метода save() измененный объект будет отправляться обратно на сервер, после чего будет выполняться программный переход на корень приложения, где будет выводиться список объектов.

И также добавим в папку ClientApp/src/app файл product-edit.component.html, который будет представлять разметку компонента:

<div *ngIf="loaded">
    <h2>Изменение данных о товаре</h2>
    <product-form [(product)]="product"></product-form>
    <div class="form-group">
        <input type="button" value="Сохранить" (click)="save()" class="btn btn-success" />
    </div>
</div>
<a routerLink="/" class="nav-link">Назад к списку</a>

Для редактирования здесь опять же используется форма, предоставляемая компонентом ProductFormComponent. А по нажатию на кнопку будет вызываться метод save().

Затем определим в каталоге ClientApp/src/app файл product-list.component.ts, который будет представлять компонент со списком объектов:

import { Component, OnInit } from '@angular/core';
import { DataService } from './data.service';
import { Product } from './product';

@Component({
    templateUrl: './product-list.component.html'
})
export class ProductListComponent implements OnInit {

    products: Product[]; 
    constructor(private dataService: DataService) { }

    ngOnInit() {
        this.load();
    }
    load() {
        this.dataService.getProducts().subscribe((data: Product[]) => this.products = data);
    }
    delete(id: number) {
        this.dataService.deleteProduct(id).subscribe(data => this.load());
    }
}

Этот компонент загружает все объекты из БД и кроме того определяет метод delete для удаления объекта по id.

Для этого компонента добавим в папку ClientApp/src/app файл product-list.component.html со следующей разметкой:

<div>
    <a routerLink="/create" class="nav-link">Добавить</a>
</div>
<table class="table table-striped">
    <thead>
        <tr>
            <td>Модель</td>
            <td>Производитель</td>
            <td>Цена</td>
            <td></td>
        </tr>
    </thead>
    <tbody>
        <tr *ngFor="let p of products">
            <td>{{p?.name}}</td>
            <td>{{p?.company}}</td>
            <td>{{p?.price}}</td>
            <td>
                <a [routerLink]="['edit', p.id]" class="btn btn-sm btn-primary">Изменить</a>
                <button (click)="delete(p.id)" class="btn btn-sm btn-danger">Удалить</button>
            </td>
        </tr>
    </tbody>
</table>

Здесь в табличном виде отображаются все загруженные объекты. Для каждого объекта определена ссылка, по нажатию на которую поизойдет переход к функционалу для редактирования выбранного объекта. Также для каждого объекта определена кнопка, по нажатию на которую будет выполняться метод delete(), который удалит выбранный объект.

Перед таблицей располагается ссылка на добавление нового объекта.

И в конце добавим в проект в папку ClientApp/src/app еще один файл not-found.component.ts, который будет представлять компонент для несуществующих маршрутов:

import { Component} from '@angular/core';

@Component({
    template: '<h2>Not Found</h2>'
})
export class NotFoundComponent {}

И зафиксируем все маршруты и сопоставим их с компонентами в файле app.module.ts:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { Routes, RouterModule } from '@angular/router';

import { AppComponent } from './app.component';
import { ProductListComponent } from './product-list.component';
import { ProductFormComponent } from './product-form.component';
import { ProductCreateComponent } from './product-create.component';
import { ProductEditComponent } from './product-edit.component';
import { NotFoundComponent } from './not-found.component';

import { DataService } from './data.service';

// определение маршрутов
const appRoutes: Routes = [
    { path: '', component: ProductListComponent },
    { path: 'create', component: ProductCreateComponent },
    { path: 'edit/:id', component: ProductEditComponent },
    { path: '**', component: NotFoundComponent }
];

@NgModule({
    imports: [BrowserModule, FormsModule, HttpClientModule, RouterModule.forRoot(appRoutes)],
    declarations: [AppComponent, ProductListComponent, ProductCreateComponent, ProductEditComponent,
        ProductFormComponent, NotFoundComponent],
    providers: [DataService], // регистрация сервисов
    bootstrap: [AppComponent]
})
export class AppModule { }

В данном случае путь "/create" будет сопоставляться с компонентом ProductCreateComponent, а путь "/edit/:id" - с компонентом ProductEditComponent. Маршрут по корневому пути будет обрабатываться компонентом ProductListComponent, а маршруты по остальным путям - компонентом NotFoundComponent.

В итоге проект будет выглядеть следующим образом:

CRUD с маршрутизацией в Angular 9 и ASP.NET Core Web API

Запустим проект, и по умолчанию обращение будет идти к корню приложения, поэтому запрос будет обрабатываться компонентом ProductListComponent, и мы увидим список объектов:

List in CRUD Angular and ASP.NET Core

А при нажатии на ссылку добавления или переходу к редактированию объекта откроется форма для ввода значений объекта:

Create and Edit in CRUD Angular and ASP.NET Core
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850