Продолжим работу с проектом из прошлой темы. И теперь в папке 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.
В итоге проект будет выглядеть следующим образом:
Запустим проект, и по умолчанию обращение будет идти к корню приложения, поэтому запрос будет обрабатываться компонентом ProductListComponent, и мы увидим список объектов:
А при нажатии на ссылку добавления или переходу к редактированию объекта откроется форма для ввода значений объекта: