将数据编辑到数据库 MEAN Stack2025年3月17日 | 阅读 8 分钟 在上一节中,我们学习了客户端路由和服务器端路由之间的区别。到目前为止,一切都运行良好。在本节中,我们将介绍帖子的编辑部分。我们将学习如何使用 MEAN Stack 使帖子可编辑。我们将使用以下步骤使帖子可编辑 1) 我们为每个帖子添加了两个按钮,即 EDIT 和 DELETE。DELETE 按钮工作正常,但 EDIT 按钮现在什么也没做。我们希望当我们点击此按钮时,我们会回到新帖子页面。它不应该是新帖子页面,但其表单应该与新帖子页面相同。所以,首先我们需要为此创建一个路由,该路由加载 post-create 组件。我们将通过以下方式通过编辑访问它 ![]() 2) 我们还需要告诉它我们要编辑哪个帖子,并且该信息应该编码在 URL 中,因此我们将以以下方式向该路径添加一个动态段 ![]() 我们将重用 post-create 组件表单。我们必须确保当我们点击 "保存帖子" 并在提交此表单并调用 onAddPost() 时,我们需要区分我们是添加新帖子还是编辑现有帖子。 现在,我们的 post-create 组件将加载到两个不同的路径,我们必须确保处理这些不同的情况。Angular 帮助我们做到这一点。我们可以通过路由器向加载的组件注入一些东西,这有助于我们识别一些路由信息,例如加载此路由的确切路径。 这很重要,因为我们将知道当我们提取帖子 ID 时处于编辑模式,如果无法提取此 ID,则处于创建模式。 3) 我们将回到我们的 post-create 组件,并在 typescript 文件中注入 ActivatedRoute。我们将它与公共属性绑定,并以以下方式从 @angular/router 导入 ![]() 此路由器包为我们提供了 ActivateRoute 对象,它包含有关我们当前所在的路由的一些重要信息。我们将在创建组件时使用该信息。 4) 最好不要在构造函数中执行此操作。相反,我们将使用 ngOnInit()。我们将以以下方式在 PostCreateComponent 类中实现它 ![]() 5) 我们将添加 ngOnInit() 方法,并在此方法中,我们将找出我们是否有帖子 ID 参数。我们将通过访问 ActivateRoute 提取它,并且在那里我们有 paramMap 对象或属性。paramMap 是一个可观察对象,我们可以订阅它,并且对于所有内置可观察对象,我们永远不需要取消订阅。 ![]() 它是可观察的,因为 URL 参数可能会在我们访问页面时更改,因为我们可能有一些点击后本质上加载相同的 angular 组件但用于不同的帖子 ID。因此,URL 中的帖子 ID 只会更改,组件将保持不变,但我们在该组件上显示的数据也需要更改。这就是我们获得可观察对象的原因。 6) 我们在订阅的第一个回调中获得一个 paramMap 对象,该回调将在参数更改时执行。我们以以下方式获得此对象 ![]() 7) 现在,我们将查看 paramMap 并检查某些参数。我们将检查它是否存在。如果此 paramMap 具有 postId,那么我们提取并使用它。如果没有 postId,那么我们处于创建模式。这将以以下方式编码 ![]() 在上面的代码中,我们创建了两个属性,即 mode 和 postId。mode 默认设置为 create,最初 postId 的值为 undefined。 如果 paramMap 具有 postId,则 mode 值将覆盖为 "edit"。否则,它保持不变。同样,如果 paramMap 具有 postId,则提取 postId 并将其存储在 postId 属性中。否则,将 null 值馈入 postId 属性。 8) 我们可能需要获取我们要编辑的帖子的信息。我们将从我们的帖子服务中获取它,所以我们将回到我们的 post.service.ts 文件。在这里,我们需要能够从我们的帖子列表中获取单个帖子,为此,我们将添加一个新方法 getPost(),并且在此方法中,我们期望获取一个 ID。 ![]() 9) 在此方法中,我们将简单地返回一个新对象,因为我们想要创建我们正在返回的对象的克隆。我们将以以下方式获取帖子 ![]() 在上面的代码中,我们使用了展开运算符(...) 来提取对象的所有属性并将它们添加到新对象中。我们使用了 this.posts,因为我们想从 posts 数组中获取该对象。find() 方法用于从帖子中获取对象,并且在此方法中,我们使用了一个函数作为参数,该函数将在数组中的每个帖子中执行。如果此函数返回 true,则返回帖子对象。此函数仅在数组中帖子的 ID 等于 getPost() 方法的 ID 参数时返回 true。 10) 在我们的 post-create 组件中,我们已经注入了我们的帖子服务,所以我们只需要加载该帖子并存储它。我们将创建一个类型为 Post 的新属性,并在 ngOnInit() 中以以下方式存储单个帖子 ![]() 11) 现在,唯一剩下要做的事情是我们将表单与该帖子数据填充,然后处理提交。我们需要确保我们可以加载此页面,为此,我们将回到我们的帖子列表组件。在此组件中,我们创建了一个用于编辑帖子的按钮,但现在我们将它变成一个锚标记,因为它将以以下方式包含一个链接 ![]() 12) 现在,我们需要用该帖子的值预填充我们的表单。我们将回到我们的 post-create.component.html 文件,在这里,我们使用了模板驱动的方法。这意味着我们必须在输入字段的 ngModel 上进行单向绑定。使用 ngModel 将其注册为控件是不够的。我们需要向 angular 提供我们想要使用的默认值的额外信息,这可以通过简单地用方括号包装 ngModel 来完成,如下所示 ![]() 现在,如果我们保存并回到我们的 angular 应用程序,我们将看到以下更改 ![]() ![]() 13) 现在,我们想确保在提交帖子时更新它,而不是添加它。为此,我们将回到我们的 post.service.ts 文件,并添加一个更新帖子新方法。在此方法中,我们期望获取 ID 和帖子数据,并以以下方式使用此数据创建一个新帖子 ![]() 14) 我们需要一个后端路由来发送此请求,所以我们将回到我们的 app.js 文件。为了更新内容,我们可以使用 put 请求来放置新资源并完全用它替换旧资源,或者我们可以使用 patch 请求只用新值更新资源。我们将以以下方式使用 put 请求 ![]() 15) 现在,我们需要使用 mongoose 来更新资源,为此,我们将使用 Post 模型并使用 updateOne() 方法。在此方法中,我们将 URL 中的 ID 作为对象和我们想要存储的新对象(即新帖子)传递。所以,首先,我们将创建具有相同 ID 的帖子,然后以以下方式将其传递给方法 ![]() 16) 我们还需要链式调用 then 块来处理成功情况。在获取结果的回调中,我们将控制台输出结果并以以下方式发送带有 JSON 数据的响应 ![]() 17) 现在,我们将回到我们的 service.ts 文件,并在 updatePost() 方法中,我们将使用本地 http 服务以以下方式向 URL 发送 put 请求 我们还需要订阅 put 请求,我们将得到响应,目前,我们只是将该响应打印到控制台。这意味着我们暂时不会在本地更新帖子。 ![]() 注意:如果您此时收到错误,即找不到属性 title,您可以忽略它。我们将在下一节中修复它。如果我们回到我们的应用程序,点击编辑并在进行一些更改后点击“保存帖子”,它将被添加为一个新帖子,而不是更新。 ![]() 18) 之所以出现此错误,是因为我们没有使用 updatePost() 方法。我们仍然在 post-create.component.ts 中添加帖子。因此,我们将进入 onAddPost() 方法,在此方法中,我们将在表单验证后检查模式。如果模式是 "create",则添加帖子,否则以以下方式更新帖子 ![]() 如果我们回到我们的应用程序并尝试编辑帖子,我们将收到以下 CORS 错误。 ![]() 19) 现在,通过进入 app.js 文件,此错误将被消除。在此文件中,我们在 "Access-Control-Allow-Methods" 中允许 put 请求 ![]() 现在,我们将再次尝试编辑帖子。 ![]() ![]() ![]() 一切都运行良好,但这里缺少两件事,即我们还没有立即更新本地数组中的帖子。我们将在下一节中这样做,我们将立即重新加载页面,因为帖子的 ID 在 URL 上可见。 下一个主题更新服务器上的数据 |
我们请求您订阅我们的新闻通讯以获取最新更新。