angular的选择模型如何判断两个对象是否相等?

问题描述 投票:0回答:1

我正在尝试使用 Angular 的选择模型在表格中预选一些用户。检索表中用户的调用和检索已选择用户的调用不同,因此实际对象不一样。

我试着在 UserProfile 类上写一个 equals 方法,这似乎没有改变任何东西。重写代码以使用 id 可以解决问题,但我想让选择模型处理实际对象而不是 id。

这是我正在使用的代码,但我希望我的问题足够清楚。

@Input() selected: UserProfile[];

ngOnInit() {
    this.selection = new SelectionModel<UserProfile>(true, this.selected);
angular angular-cdk selectionmodel
1个回答
2
投票

SelectionModel
是作为
@angular/cdk
库的一部分实现的。该文档可以在 Angular Material Documentation 的Collections页面中找到。

在代码中我们使用以下导入:

import { SelectionModel } from '@angular/cdk/collections';

SelectionModel
是使用本机 Javascript
Set()
对象构建的,可以在源代码中找到code

private _selection = new Set<T>();

Set
对象允许您存储任何类型的unique 值,无论是原始值还是对象引用。

SelectionModel
的实现通过使用
Set.has
方法检查该集合中是否包含一个项目。


首先要考虑的是,在Javascript中,两个不同的对象实例总是不相等

const obj1 = { a: 1, b: 2 };
const obj2 = { a: 1, b: 2 };
obj1 !== obj2; // => true

所以,会出现以下情况:

const mySet = new Set();
const obj1 = {a: 1, b: 2};
const obj2 = {a: 1, b: 2};

mySet.add(obj1);

mySet.has(obj1); // -> Output: true
mySet.has({a: 1, b: 2}); // -> Output: false
mySet.has(obj2); // -> Output: false

mySet.add(obj2)   // obj2 is referencing a different object, so the object will be added in the set

mySet.size; // -> Output: 2

mySet.forEach((value) => {
  console.log(value);
});
// Output: {a: 1, b: 2}
// Output: {a: 1, b: 2}

有关 JS 的更多信息

Set()
这里.


更新 (27.03.2023) - Angular 14+

Angular 14开始,

SelectionModel
支持自定义
compareWith
函数
- 可选传递的函数以自定义
Selection Model
如何唯一标识项目:

compareWith: (o1: T, o2: T) => boolean

https://material.angular.io/cdk/collections/api#SelectionModel

因此,我们可以通过使用它们的属性(例如:

name
属性)来比较选择模型中的对象。比较函数返回一个布尔值:

interface IPeriodicElement {
  name: string;
  symbol: string;
  ...
}

customCompareFn = (o1: IPeriodicElement, o2: IPeriodicElement) =>
    o1.name === o2.name;

初始化我们的

SelectionModel
如下:

public selection = new SelectionModel<IPeriodicElement>(
    true,
    this.initialSelection,
    true,
    (o1: IPeriodicElement, o2: IPeriodicElement) =>
    o1.name === o2.name;
  );

Stackblitz:https://stackblitz.com/edit/angular-ntmyut?file=src/app/selection-example/selection-example.component.ts


对于角<=13

没有方法可以覆盖

Set
对象中的比较方法,所以我使用非常流行的名为
immutable-js
的库编写了自己的
SelectionModel
-SelectionModelImmutableJS实现。实施的灵感来自以下answer.

为了简化,通过使用

immutable-js
,我们将有以下情况:

const { Map, Set } = require('immutable');
const map1 = Map({ a: 1, b: 2 });
const map2 = Map({ a: 1, b: 2 });

map1 !== map2; // => true, two different instances are not reference-equal
map1.equals(map2); // true, but are value-equal if they have the same values
const set = Set().add(map1);
set.has(map2); // true, because these are value-equal

选择模型的代码有点太大,我不会将其内联发布 - 它可以在工作演示中找到。

在我们将使用的应用程序中:

import { SelectionModelImmutableJS } from './selection-model-immutable';

.....


public selection = new SelectionModelImmutableJS<IPeriodicElement>(
    true,
    this.initialSelection
  );

完整的工作演示: https://stackblitz.com/edit/angular-ivy-wnvohl

© www.soinside.com 2019 - 2024. All rights reserved.