javascript - 从角度发送删除请求以表达
问题描述
我正在尝试编写一个端点来从数据库中删除一个项目。将被删除的项目将由用户通过复选框在表格上选择。
对于前端,我使用 angular,后端 mongoose 和 express。
在角度方面,我有一个列出项目的表格和一个在单击删除按钮时显示的确认对话框。当用户检查一个项目并单击删除图标(按钮)时,我可以通过“ngFor”获取产品信息,但在确认对话框中单击“是”后我无法实现将项目数据发送到数据库。
我试图分配方法并通过一个布尔变量在条件下调用它们。但是出现“响应为空”错误。
组件.html
<table
id="mytable"
class="table table-bordred table-dark table-hover table-striped"
>
<thead>
<th><input type="checkbox" /></th>
<th>Category</th>
<th>Product Name</th>
<th>Description</th>
<th>Price</th>
<th>Edit</th>
<th>Delete</th>
</thead>
<tbody *ngFor="let product of products;let i=index;">
<tr>
<td>
<input
type="checkbox"
class="checkall"
id="checked"
(change)="selectCheckbox($event,product._id)"
/>
</td>
<td>{{product.category}}</td>
<td>{{product.name}}</td>
<td>{{product.description}}</td>
<td>{{product.price}}</td>
<td>
<p data-placement="top" data-toggle="tooltip" title="Edit">
<button
class="btn btn-primary btn-xs"
data-title="Edit"
data-toggle="modal"
data-target="#edit"
>
<i class="fas fa-edit fa-xs"></i>
</button>
</p>
</td>
<td>
<p data-placement="top" data-toggle="tooltip" title="Delete">
<button
(click)="deleteAProduct(product)"
class="btn btn-danger btn-xs"
data-title="Delete"
data-toggle="modal"
data-target="#delete"
>
<i class="far fa-trash-alt fa-xs"></i>
</button>
</p>
</td>
</tr>
</tbody>
</table>
<div
class="modal fade"
id="delete"
tabindex="-1"
role="dialog"
aria-labelledby="edit"
aria-hidden="true"
>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button
type="button"
class="close"
data-dismiss="modal"
aria-hidden="true"
>
<i style="position: absolute;left: 0.25rem;" class="fas fa-times"></i>
</button>
<h4 class="modal-title custom_align" id="Heading">Bu Ürünü Sil</h4>
</div>
<div class="modal-body">
<div class="alert alert-danger">
<span class="glyphicon glyphicon-warning-sign"></span> Are you sure to
delete this product?
</div>
</div>
<div class="modal-footer ">
<button (click)="intentToDelete()" class="btn btn-success">
<span class="glyphicon glyphicon-ok-sign"></span>Yes
</button>
<button type="button" class="btn btn-default" data-dismiss="modal">
<span class="glyphicon glyphicon-remove"></span>Cancel
</button>
</div>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
菜单模型
const mongoose = require("mongoose");
const menuSchema = mongoose.Schema({
company: { type: mongoose.Schema.Types.ObjectId, ref: "Company" },
products: [
{
name: String,
price: {
type: Number,
currency: ["TRY", "EUR", "USD"]
},
description: String,
state: Boolean,
imgUrl: String,
category: String
}
]
});
组件.ts
confirm = false;
constructor(private fb: FormBuilder, private menuService: MenuService) {}
intentToDelete() {
this.confirm = true;
}
deleteAProduct(product) {
if (this.confirm === true) {
try {
this.menuService.deleteProduct(product).subscribe(data => {
console.log(data);
});
} catch (error) {
console.log(error);
}
}
}
组件.service.ts
deleteProduct(body): Observable<any> {
return this.http.delete(BASEURL + '/menu/delete-product', body);
}
端点
async deleteProduct(req, res) {
const productId = req.body._id;
await Menu.deleteOne({
_id: productId
})
.then(info => {
res.status(httpStatus.Ok).json({ message: "product deleted" }, info);
})
.catch(err => {
res
.status(httpStatus.INTERNAL_SERVER_ERROR)
.json({ message: "error occured!", err });
});
}
解决方案
我们通常在 url 中而不是在正文中发送已删除项目的 id。
所以我会像这样改变我的角度服务:
deleteProduct(body): Observable<any> {
return this.http.delete(BASEURL + '/menu/delete-product/'+ body._id);
}
而在 express 端,我们可以使用 req.params._id 读取这个 id,但是删除路由签名必须是这样的 router.delete("/:_id", controller.deleteProduct)
。
要从菜单中删除产品,您可以使用以下功能:
deleteProduct(req, res) {
const productId = req.params._id;
const companyId = "5df28fe8a8e0c23240a147a8"; //TODO: set the logined company id
Menu.findOneAndUpdate(
{ company: companyId },
{
$pull: { products: { _id: productId } }
},
{
new: true
}
)
.then(doc => {
console.log("Doc: ", doc);
res.status(200).json({ message: "product deleted", doc });
})
.catch(err => {
console.log("Error: ", err);
res.status(500).json({ message: "error occured!" });
});
}
测试:
假设您有一个包含 2 种产品的菜单,如下所示:
{
"_id": "5df36c7353876b368864bd3a",
"company": "5df28fe8a8e0c23240a147a8",
"products": [
{
"_id": "5df36c7353876b368864bd3c",
"name": "Product1",
"price": 11,
"currency": "TRY"
},
{
"_id": "5df36c7353876b368864bd3b",
"name": "Product2",
"price": 22,
"currency": "TRY"
}
],
"__v": 0
}
如果要删除 id 为 5df36c7353876b368864bd3c 的 Product1,请将此 id 发送到您的删除路由,响应将如下所示:
{
"_id": "5df36c7353876b368864bd3a",
"company": "5df28fe8a8e0c23240a147a8",
"products": [
{
"_id": "5df36c7353876b368864bd3b",
"name": "Product2",
"price": 22,
"currency": "TRY"
}
],
"__v": 0
}
另请注意,我修复了您在评论中提到的菜单架构。它必须具有单独的价格和货币字段,如下所示:
const menuSchema = mongoose.Schema({
company: { type: mongoose.Schema.Types.ObjectId, ref: "Company" },
products: [
{
name: String,
price: Number,
currency: {
type: String,
enum: ["TRY", "EUR", "USD"]
},
description: String,
state: Boolean,
imgUrl: String,
category: String
}
]
});
或者,您可以将其保存在具有价格和货币字段的对象字段中。
推荐阅读
- javascript - 带有实时数据的 Vue 刷新页面
- scala - 使用另一个 DF 的列过滤 DF(两个 DF 中的列相同)Spark Scala
- powershell - 我无法解决“'System.OutOfMemoryException' 类型的异常”这个错误
- python - 将粗体文本写入文件
- google-cloud-platform - 谷歌云外壳,以便在注销时继续该过程
- javascript - 在 vuetify 的日历上不工作 prev()
- python - 从表中检索数据并将其注册为 Django 管理页面上的模型
- swift - Swift IOS 从 pod install 'FirebaseAnalytics' 中排除 google app mesurment 框架
- php - 静态页面的自动 Laravel 路由
- linux - 如何 ssh 进入在不同网络上运行的 docker 容器?