在 Angular 中使用异步管道设置选择元素的选定项目

2024-05-05

角度专家!我试图理解 Angular 中的异步管道,但我陷入了一个基本场景。我在用户界面中有两个选择元素,一个包含帖子,一个包含相关评论。我想将一个帖子(最后一个)设置为显示帖子的选择元素的最初选择的帖子,并且我想使用所选项目来过滤第二个选择中的相关评论。这在我的代码中不起作用,我在 Stackblitz 中创建了一个简化版本:

https://stackblitz.com/edit/angular-p6ynuy https://stackblitz.com/edit/angular-p6ynuy

你们中的任何人都可以向我解释我做错了什么吗?这是相关的代码片段和 HTML:

ngOnInit() {
    this.postList$ = this.getPostList();

    // latestPost$ is not is use yet, but maybe it could be used to set the selected post?
    this.latestPost$ = this.postList$ 
      .pipe(
        map(posts => posts[posts.length - 1])
      );

    this.selectedPost$ = combineLatest([
      this.postList$,
      this.postSelectedAction$
    ])
      .pipe(
        map(([posts, selectedPostId]) => posts.find(post => post.id === selectedPostId))
      );

    this.commentList$ = this.selectedPost$
      .pipe(switchMap(
        post => this.getCommentList(post)
      ));
  }


<select [ngModel]="selectedPost$ | async" (change)="onSelected($event.target.value)">
  <option *ngFor="let post of postList$ | async" [ngValue]="post">
    {{post.id}} {{post.title}}
  </option>
</select>
<select>
  <option *ngFor="let comment of commentList$ | async" [ngValue]="comment">
    {{comment.id}} {{comment.postId}} {{comment.name}}
  </option>
</select>

Angular 默认通过引用比较对象

你快到了。问题是你的select得到一个列表options 引用Posts 作为一部分ngFor。现在要找出哪个option当前已选择,Angular 会比较每个post当前值为的对象selectedPost$ | async.

默认情况下,完成的方法是使用===操作员。这===运算符按值比较基元,但按引用比较对象。例子:

console.log('a' === 'a');
const obj = {'a': 'b'};
const obj2 = obj;
console.log(obj === obj2);
console.log(obj === {'a': 'b'});

所以为了post算作同一个帖子selectedPost$ | async,它们必须是实际相同的对象,而不仅仅是看起来相同的对象。

您实际上检索同一帖子的多个副本,而不仅仅是一个帖子

现在情况并非如此:当您使用async管道,在更改检测期间,可能会发生从 API 重新加载帖子的情况。当您查看浏览器的网络选项卡时,您实际上可以看到有三个请求:

所有请求的响应负载都是相同的,但是Post对象被返回三次,它们被存储在内存中三次。 JavaScript 无法知道它们实际上是相同的,并且===比较回报false.

解决方案:提供您自己的解决方案compareWith功能

你怎么解决这个问题?你可以帮忙Angular比较一下Post正确地在你的对象select。你只需要问自己这个问题:我怎么知道两个Post对象实际上是同一个对象?在这种情况下,答案是:当它们具有相同的 ID 时。

现在,您可以为 Angular 编写自己的指令来比较对象或您的选择:只需添加一个compareWith输入到选择:

<select [ngModel]="selectedPost$ | async" 
(change)="onSelected($event.target.value)"
[compareWith]="comparePosts"
>

现在 Angular 知道使用一种名为comparePosts比较两个帖子。现在这个方法看起来怎么样?例如这样:

comparePosts(p1: Post, p2: Post) {
    return p1.id === p2.id;
}

现在 Angular 知道如何正确比较两个Post对象,你的问题就解决了。

PS:请务必写一个更好的comparePosts方法比我做的好,例如也处理得当undefined and null values.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Angular 中使用异步管道设置选择元素的选定项目 的相关文章

随机推荐

  • postgresql 中带有分组的嵌套聚合函数

    我正在尝试使用嵌套聚合函数和分组来获得总和的平均值 我想做的是 SELECT AVG SUM x GROUP BY y WHERE GROUP BY 也就是说 对于返回的每一行 我希望其中一个字段是总和的平均值 其中每个总和都位于 y 相同
  • 如何将 Properties.Settings.Default 的副本保存到变量?

    我有一个 恢复默认值 选项对话框中的按钮 并且想要恢复仅在此表单中受影响的值 而不是整个 Properties Settings Default 所以我尝试 var backup Properties Settings Default Pr
  • 如何返回空实体的响应状态 405?

    如何在 java REST 中返回带有空实体的响应状态 405 POST Path path public Response createNullEntity return Response created null status 405
  • 如何将标签放在 Flutter DataColumn 小部件中?

    我可以将 DataCell 放在 DataRow 中居中 但是对于 DataColumn 标签如何做到这一点 我希望第一个 DataColumn 左对齐 其余的居中 将标签包裹在 Center 小部件中不会生效 new DataColumn
  • MS-Access:合并彼此“下方”的两个表

    我的 Access 数据库中有两个表 它们看起来像这样 Table1 Kabelnummer Column1 Column2 Column3 1 x x x 2 x x x
  • Python:如何检索每年的谷歌学术引用?

    我正在尝试从 Google Scholar 个人资料中检索信息 我有url from bs4 import SoupStrainer BeautifulSoup from urllib2 import Request urlopen url
  • 我可以在 Android 上使用带有文本视图的列表视图和图像图标吗

    我需要一个像下面的 Android 应用程序那样的列表视图 由于我无法发布图片 所以应该是这样的 图片在这里 一些自由文本 用户名等 这是你的任务 任务1 gt 任务2 gt 任务 1 和任务 2 是将从数据库动态获取的列表 我试图拥有一个
  • 在Java中运行命令行[重复]

    这个问题在这里已经有答案了 有没有办法在 Java 应用程序中运行此命令行 java jar map jar time rel test txt debug 我可以用命令运行它 但我无法在 Java 中运行它 Runtime rt Runt
  • 将大块位图转换为 3 维位图

    Problem 我需要这个大量的数据作为输入 对于基于C的arduino 这是上面示例中所需格式的大量数据 const byte bitmap 8 8 0xFF 0x81 0x81 0x81 0x81 0x81 0x81 0xFF 0x81
  • 如何在点击 Qtablewidget 单元格时获取放置在该单元格中的小部件的行号?

    我正在尝试的是当用户选择项目时获取 QcomboBox 的行号 虽然使用它很容易获得单元格的列和行 cellClicked int int 信号 但仅当单元格上没有小部件时才有效 那么如果单元格中放置了小部件 如何获取行号 Note 所有组
  • SVG 视图框显示屏幕外项目

    我正在使用 HTML5 制作游戏svg标签为图形提供多分辨率显示 游戏的大部分内容已经完成 但在测试中我刚刚遇到了一个主要错误 其中涉及 SVG 对象可见 尽管在非本机分辨率下位于视图框之外 我不确定这是否是我的代码或浏览器本身的缺陷 Go
  • 从 WPF 打印/报告的最佳方法是什么? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何在单击片段的按钮时替换该片段?

    我有一个包含多个片段的活动 Activity 最初有片段 其中有两个按钮 单击此按钮后 我必须用新片段替换该片段 每个片段都有各种小部件 并将当前片段替换为各种事件 这是我的问题 我怎样才能实现这个目标 给我建议 您可以用 Fragment
  • 从现有 MongoDB 创建可视化的工具[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我接手了一个现有 MongoDB 的项目 我想获得现有数据的视觉图像 图表等 显然 MongoDB 与
  • Android USB_DEVICE_ATTACHED 持久权限

    如何让 Android 在每次重新连接 USB 设备时都不再请求权限 我想让它记住 USB 设备的 默认使用 复选标记 这样我就不必每次都向同一设备授予权限 我以编程方式检测 USB 设备 Android 手机 何时连接到我的主机设备 An
  • 如何找到一组值的精确匹配?

    我有一个简单的表来存储师生关系 以显示学生正在上谁的课或老师正在教谁 无论哪种方式 为便于阅读 按老师排序 CREATE TABLE TS RELATIONSHIP Teacher NVARCHAR 10 Student NVARCHAR
  • 求反射角的弧度

    我正在编写一个简单的 Flash 游戏 只是为了学习 Flash 并提高我的数学能力 但我对弧度感到非常困惑 因为这对我来说是新的 到目前为止 我所做的是使用鼠标 单击并释放 使用弧度向该方向射出一个球 现在我想要发生的是 当球撞到墙壁时
  • Node exec 无权执行脚本

    直到最近 它都运行良好 但是当我今天尝试使用它时 它无法正常运行 它返回以下错误 错误 命令失败 bin sh c home pi RPi Computer Power RPi Server routes scripts hash js 1
  • Cordova 3.0,应用程序错误与服务器的连接失败。 (暂停)

    我在尝试加载本地 index html 文件时遇到超时问题 但我不知道如何增加默认的 20 秒超时时间 我见过人们在 droidgap 扩展 onCreate 方法中使用以下几行的帖子 super setIntegerProperty lo
  • 在 Angular 中使用异步管道设置选择元素的选定项目

    角度专家 我试图理解 Angular 中的异步管道 但我陷入了一个基本场景 我在用户界面中有两个选择元素 一个包含帖子 一个包含相关评论 我想将一个帖子 最后一个 设置为显示帖子的选择元素的最初选择的帖子 并且我想使用所选项目来过滤第二个选