【问题标题】:Sending delete request from angular to express从角度发送删除请求以表达
【发布时间】:2019-12-13 19:06:34
【问题描述】:

我正在尝试编写一个端点来从数据库中删除一个项目。 将被删除的项目将由用户在 通过复选框的表格。

对于前端,我使用 angular,对于后端 mongoose 和 express。

在角度方面,我有一个列出项目的表格和一个在单击删除按钮时显示的确认对话框。当用户检查一个项目并且 点击删除图标(按钮),我可以通过“ngFor”获取产品信息 但是在确认对话框上单击“是”后,我无法将项目数据发送到数据库。

我尝试分配方法并通过布尔变量在条件中调用它们。但出现“response is empty”错误。

component.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
    }
  ]
});

component.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);
    }
  }
}

component.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 });
    });
}

【问题讨论】:

    标签: javascript angular express


    【解决方案1】:

    我们通常在 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
    }
    

    请注意,我还修复了您在 cmets 中提到的菜单架构。 它必须具有单独的价格和货币字段,如下所示:

    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
        }
      ]
    });
    

    或者您可以将其保存在包含价格和货币字段的对象字段中。

    【讨论】:

    • 评论不用于扩展讨论;这个对话是moved to chat
    • @SamuelLiew 谢谢你,但奇怪的是我没有出现“移动聊天”选项。可能是因为某些网络政策。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-29
    • 2021-12-01
    • 2019-12-04
    • 2012-01-09
    • 2020-07-11
    • 1970-01-01
    相关资源
    最近更新 更多