我正在尝试根据大子数组的值来过滤父数组,但是我的过滤方法无法正常工作,并且用户界面没有得到更新。
这是我的过滤器功能。
filterIt($event) {
this.filter.RegCategoryName = $event.target.value;
this.dataObject = staticData.filter(value =>
value.List.filter(ch => ch.RegistrationCategory.filter(gChild =>
Object.keys(this.filter).every(ob =>
String(gChild[ob]).toLowerCase().includes(String(this.filter[ob]).toLowerCase())
)
)).length
)
}
期望:
当用户键入new Course
时,它应仅在“程序”列中显示DP Programme
。
答案 0 :(得分:2)
您可以结合使用map
,filter
和some
Array
方法来实现。使用扩展运算符...
,以使原始数组不会在子对象中得到更新。
filterIt($event) {
this.filter.RegCategoryName = $event.target.value;
this.dataObject = staticData.filter(value => {
const data = { ...value };
data.List = data.List.map(ch => {
const list = { ...ch };
list.RegistrationCategory = list.RegistrationCategory.filter(gChild => {
return gChild.RegCategoryName.toLowerCase().indexOf(this.filter.RegCategoryName.toLowerCase()) !== -1
});
return list;
});
return data.List.some(list => !!list.RegistrationCategory.length);
});
}
注意:避免使用首字母大写的变量名。
这是StackBlitz上的一个有效示例。
说明:
这里使用的结构非常复杂,所以我想我将从内而外开始。让我们从最里面的filter
开始。
list.RegistrationCategory = list.RegistrationCategory.filter(gChild => {
return gChild.RegCategoryName.toLowerCase().indexOf(this.filter.RegCategoryName.toLowerCase()) !== -1
});
filter()
方法创建一个新数组,其中包含所有通过由提供的功能实现的测试的元素。
这应该足够清楚。此处使用的条件与Angular Material的mat-table
过滤器中使用的条件相同。如果RegCategoryName
包含搜索词,则会进行过滤。我之所以说“包含”,是因为即使您的搜索字词为new Course
,它也会匹配ew
。如果这不是您想要的,则可以改用startsWith
。仅当您的搜索字词为new
而不是ew
时,这才匹配。
list.RegistrationCategory = list.RegistrationCategory.filter(gChild => {
return gChild.RegCategoryName.toLowerCase().startsWith(this.filter.RegCategoryName.toLowerCase())
});
移动到第一个父数组List
。我们不想filter
或在此处更改对象。取而代之的是,我们只需要同一个对象,但是要使用新的过滤后的RegistrationCategory
。这很适合map
,因为map
返回的数组具有相同数量的对象(如果需要,可以对对象中的元素进行一些修改)。
map()
方法创建一个新数组,其结果是在调用数组中的每个元素上调用提供的函数。
因此,在我们的map
中,我们将使用上面创建的RegistrationCategory
更新filter
。我们无法直接修改ch
,因为那样会改变原始对象。因此,我们将使用spread syntax将ch
浅克隆到变量list
中,并使用上述RegistrationCategory
在新的list
变量中修改filter
并返回对象。现在,只需更新每个对象中的List
,就可以为我们提供RegistrationCategory
数组。
现在,作为最后一部分,我们需要从filter
到staticData
。就像我们在map
中所做的那样,由于我们不想更新原始对象,因此将在此处再次使用传播语法。 data.List
现在将通过内部过滤器对每个RegistrationCategory
进行过滤,因此我们只需要根据true
数组是否返回一个false
/ List
值包含RegistrationCategory
长度大于0的任何对象。为此,我们可以使用some
。
some()
方法测试数组中的至少一个元素是否通过了由提供的函数实现的测试。它返回一个布尔值。
因此,如果RegistrationCategory
数组中的任何List
的长度都大于0(因为这是我们关心的全部,那么在我们最里面的过滤器过滤{{ 1}}),则返回RegistrationCategory
,并将其添加到过滤后的List
中。
通过这种方式,我们得到true
的每个对象,它们的dataObject
数组包含一个对象,其中staticData
包含一些数据。
我希望这可以弄清楚为什么您的代码有问题以及为什么不能对所有三个数组使用过滤器。