平均スタックショッピングアプリ(Angular 5)を作成していました。すべての製品のリストと削除ボタンを備えた製品管理コンポーネントを作成しました。削除ボタンは機能しますが、製品はデータベースから削除されたため、これまでテーブルにリストされています。そのため、削除後にコンポーネントを再レンダリングまたは更新するための可能な方法はないかと思いました。同じページに移動しようとしましたが、angularはそれを許可しないため、機能しません。だれでも助けてください。stackoverflowで私のクエリに対する具体的な回答が見つからなかったため、聞いてください。
私のmanage-product.component.tsは:-です
import { Component, OnInit } from '@angular/core';
import { ProductManageService, ProductDetails } from '../product-manage.service';
import { AllService } from '../all.service';
import { HttpClientModule, HttpClient } from '@angular/common/http';
import { Router } from '@angular/router';
import { Location } from '@angular/common';
@Component({
selector: 'app-manage-product',
templateUrl: './manage-product.component.html',
styleUrls: ['./manage-product.component.css']
})
export class ManageProductComponent implements OnInit{
prodData : ProductDetails = {
prodName: '',
prodPrice: '',
prodImage: '',
prodSize: ''
}
data: any=[];
constructor(private add:ProductManageService,
private router: Router,
private http:HttpClient,
private allService :AllService,
private location : Location) { }
addProduct(){
this.add.addProduct(this.prodData).subscribe(()=>{
console.log("SENT",this.prodData);
},(err)=>{
console.log("Error",err);
})
}
delFunc(id){
// console.log("Delete ",id);
this.add.deleteProd(id);
this.router.navigateByUrl("/reload");
}
ngOnInit() {
this.allService.getAlldata().subscribe(data =>{
console.log("data",data);
this.data = data;
});
console.log(this.data);
}
}
管理コンポーネントの私のhtmlファイルは:-
<div class="container">
<form (submit)="addProduct()">
<div class="form-group">
<label for="name">Product Name</label>
<input name="prodName" type="text" class="form-control" id="name" placeholder="Tshirt" [(ngModel)]="prodData.prodName">
</div>
<div class="form-group">
<label for="price">Price</label>
<input name="prodPrice" type="text" class="form-control" id="price" placeholder="1.1" [(ngModel)]="prodData.prodPrice">
</div>
<div class="form-group">
<label for="image">Price</label>
<input name="prodImage" type="text" class="form-control" id="image" placeholder="Link to image" [(ngModel)]="prodData.prodImage">
</div>
<div class="form-group">
<label for="size">Price</label>
<input name="prodSize" type="text" class="form-control" id="size" placeholder="M" [(ngModel)]="prodData.prodSize">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
<table class="table table-hover">
<tr>
<th>Product Name</th>
<th>Product Price</th>
<th>Product Size</th>
<th> </th>
</tr>
<tr *ngFor="let prod of data">
<td>{{ prod.prodName }}</td>
<td>{{ prod.prodPrice }}</td>
<td>{{ prod.prodSize }}</td>
<td>
<input type="button" class="btn btn-danger" routerLink="/reload" (click) = "delFunc(prod._id)" class="del-btn" value="Delete">
</td>
</tr>
</table>
</div>
必要な場合はapp.module.ts:-
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { HttpModule } from '@angular/http';
import { FormsModule } from '@angular/forms';
import { RouterModule, Routes } from '@angular/router';
import { AllService } from './all.service';
import {AuthGuardService} from './auth-guard.service';
import {AuthenticationService} from './authentication.service';
import { ProductManageService } from './product-manage.service';
import { AppComponent } from './app.component';
import { FrontComponent } from './front/front.component';
import { ContentComponent } from './content/content.component';
import { ProductDetailComponent } from './product-detail/product-detail.component';
import { RegisterComponent } from './register/register.component';
import { LoginComponent } from './login/login.component';
import { ProfileComponent } from './profile/profile.component';
import { ManageProductComponent } from './manage-product/manage-product.component';
const routes = [
{
path: '',
component: ContentComponent
},
{
path: 'product',
component: ProductDetailComponent
},
{
path: 'login',
component: LoginComponent
},
{
path: 'register',
component: RegisterComponent
},
{
path: 'profile',
component: ProfileComponent,
canActivate: [AuthGuardService]
},
{
path: 'manage',
component: ManageProductComponent,
},
{ path: 'reload',
redirectTo: 'manage',
pathMatch: 'full'
},
];
@NgModule({
declarations: [
AppComponent,
FrontComponent,
ContentComponent,
ProductDetailComponent,
RegisterComponent,
LoginComponent,
ProfileComponent,
ManageProductComponent
],
imports: [
BrowserModule,
FormsModule,
HttpClientModule,
HttpModule,
RouterModule.forRoot(routes, {
onSameUrlNavigation: 'reload'
}),
],
providers: [
AllService,
AuthenticationService,
AuthGuardService,
ProductManageService
],
bootstrap: [AppComponent],
exports: [RouterModule]
})
export class AppModule { }
API呼び出しの後にモデル(data
)が更新されなかったため、テーブルは更新されていません。モデルを更新する方法はいくつかありますが、この回答ではオプション3または2をお勧めします。
すでに述べたように、最初の方法はビューモデルの配列から要素を削除することです:
_delFunc(id){
this.add.deleteProd(id);
this.data = this.data.filter(item => item.id != id);
}
_
このアプローチの欠点はアイテムがフロントエンドで削除されている場合でも、バックエンドのデータベースから実際に正常に削除されたことをどのように確認できるのですか?意味、アイテムはthis.add.deleteProd(id)
が適切に機能せず、オブジェクトが実際にバックエンドで削除されなかった場合でも、フロントエンドHTMLテーブルから削除されます。したがって、フロントエンドビューがバックエンドの現実を正確に表しているかどうかはわかりません。
2番目の方法は、バックエンドに再度クエリを実行してテーブルを「リロード」することです。これは、関数を呼び出してデータを再度ロードするだけなので、「最小限の作業」が必要です。
_delFunc(id) {
this.add.deleteProd(id)
.subscribe(()=> {
this.fetchData();
});
}
ngOnInit() {
this.fetchData();
}
fetchData() {
this.allService.getAlldata().subscribe(data =>{
this.data = data;
});
}
_
ここでは、現実の「正確さ」を得ますが、削除するたびに2つのREST呼び出しを行うため、パフォーマンスが犠牲になります。
番目の方法は「ほとんどの作業」を行いますが、現実の正確さとパフォーマンスの間の妥協点を提供します。基本的に、データベースの削除を行った後、バックエンドREST /のようにバックエンドを書き直す必要があります。 APIメソッドは、現在データベースにある新しいデータセットを返します。
次に、Angularコンポーネントでこのようなことを行うことができます:
_delFunc(id) {
this.add.deleteProd(id)
.subscribe(newData => {
this.data = newData;
});
}
_
これは、バックエンドコードを制御できることを前提としています。 this.data = newData.json();
メソッドが返す内容によっては、代わりにthis.add.deleteProd(id)
を実行する必要がある場合があります。
状況に最適なオプションを選択してください。これで問題が解決するかどうかお知らせください。
ページをリロードする必要はありません。テンプレート側からインデックスを渡し、削除が成功したときにそのデータをインデックスから削除するだけです。
テンプレート側
<tr *ngFor="let prod of data;let i = index">
....
<input type="button" class="btn btn-danger" (click) = "delFunc(prod._id,i)" class="del-btn" value="Delete">
....
</tr>
コンポーネント側:
delFunc(id , index){
// console.log("Delete ",id);
this.add.deleteProd(id).subscribe(()=>{
this.data.splice(index, 1);
});
}
オブジェクト全体を渡すようにクリックイベントを変更します。
<input type="button" class="btn btn-danger" routerLink="/reload" (click) = "delFunc(prod)" class="del-btn" value="Delete">
そして、あなたのdelFuncのような:
delFunc(prod){
this.data.splice(this.data.indexOf(prod), 1);
this.add.deleteProd(prod._id);
}
ナビゲートする必要はありません。テンプレートの作成に使用されるデータから削除された製品を削除する必要があります。
delFunc(id){
// console.log("Delete ",id);
this.add.deleteProd(id);
const item = this.data.find(item => item.id === id);
this.data.splice(this.data.indexOf(item)));
}
もちろん、単にデータをトリガーしてリロードし、再度バックエンドを呼び出すこともできますが、これは最適ではありません。
This.dataの製品をインデックス経由で削除できます。
このためのコードを変更します。
[〜#〜] html [〜#〜] ....
<tr *ngFor="let prod of data; let i = index;">
....
<input type="button" class="btn btn-danger" routerLink="/reload"
(click) = "delFunc(prod._id, i)" class="del-btn" value="Delete">
。ts
delFunc(id, index){
// console.log("Delete ",id);
this.add.deleteProd(id, index);
this.data(index, 1);
//this.router.navigateByUrl("/reload"); }