我正在尝试使用 Angular 的选择模型在表格中预选一些用户。检索表中用户的调用和检索已选择用户的调用不同,因此实际对象不一样。
我试着在 UserProfile 类上写一个 equals 方法,这似乎没有改变任何东西。重写代码以使用 id 可以解决问题,但我想让选择模型处理实际对象而不是 id。
这是我正在使用的代码,但我希望我的问题足够清楚。
@Input() selected: UserProfile[];
ngOnInit() {
this.selection = new SelectionModel<UserProfile>(true, this.selected);
SelectionModel
是作为 @angular/cdk
库的一部分实现的。该文档可以在 Angular Material Documentation 的Collections页面中找到。
在代码中我们使用以下导入:
import { SelectionModel } from '@angular/cdk/collections';
SelectionModel
是使用本机 JavascriptSet()
对象构建的,可以在源代码中找到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;
);
对于角<=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
);