【问题标题】:Angular 11 : Functionality to filter List Table via Two Multi-select DropdownsAngular 11:通过两个多选下拉列表过滤列表的功能
【发布时间】:2021-08-24 02:23:33
【问题描述】:

我目前正在尝试解决过滤对象列表所需的逻辑:
(competitions.data.ts) 见下文
通过两个多选下拉菜单(其中一个或多个元素可以标记为从每个下拉菜单中选择):
bikes.data.tscountries.data.ts见下文
这样只有列表中的记录与我根据其中包含的数据选择的内容相关。两个下拉菜单都需要一起作为过滤器相互配合,以缩小列表数据的范围。

bikes.data.tscountries.data。 ts 是将用于过滤的数据的两组数据,而 Competitions.data.ts 是要过滤并显示在列表中的数据。如果没有过滤器处于活动状态,它应该只返回原始数据集。

示例屏幕:

按自行车下拉列表中的山地和电动(已选择)过滤以及国家/地区下拉列表中的 GB 和 FR(已选择)应该会在列表中返回相关的过滤结果。

bikes.data.ts(过滤 1 个数据):

export class BikeData {
public static bikes: Bike[] = [  
  {
    'id': '0luT3vVGeS',
    'index': 1,
    'isActive': true,
    'name': 'Electric',
    'picture': '../../assets/images/data/bike-icons/EL.jpg'
  },
  {
    'id': 'o4IGM7T5qb',
    'index': 2,
    'isActive': true,
    'name': 'Mountain',
    'picture': '../../assets/images/data/bike-icons/MN.png'
  },
  //....
 ]
}

countries.data.ts(过滤 2 个数据)

export class CountryData {
public static countries: Country[] = [
  {
    'id': 'WWvtHXaHuO',
    'index': 1,
    'isActive': true,
    'name': 'France',
    'picture': '../../assets/images/data/flags/FR.png',
    'abbrv': "FR"
  },
  {
    'id': 'ZU479oD4RF',
    'index': 2,
    'isActive': true,
    'name': 'Great Britain',
    'picture': '../../assets/images/data/flags/GB.png',
    'abbrv': "GB"
  },
//...
 ]
}

competitions.data.ts

export class CompetitionData {
public static competitions: Competition[] = [
  {
    'id': '0luT3vVGeS',
    'index': 1,
    'isActive': true,
    'title': 'Scotland Mountain Tour',
    'host': 'Scotland Cycles',
    'bike': 'Mountain',
    'country': 'GB',
    'prizePoolTotal': 500000,
    'date': "Sat May 29 2021 11:00",
    'timezone': 'GMT',
    'totalSpaces': 3000,
    'availableSpaces': 1500
  },
  {
    'id': '5lOu8vIUeG',
    'index': 2,
    'isActive': true,
    'title': 'South France Electric',
    'host': 'FR Electric',
    'bike': 'Electric',
    'country': 'FR',
    'prizePoolTotal': 57000,
    'date': "Sat May 29 2021 11:00",
    'timezone': 'GMT',
    'totalSpaces': 300,
    'availableSpaces': 200
  },
//...
 ]
}

我目前所拥有的
我认为在我的列表中实现了一个管道,如下所示:

  <tbody *ngFor="let competition of competitions | tableFilter: filterVar; let i = index"

将是一个好的开始。然后我在我的 table-filter.pipe.ts 文件中声明使用这个过滤器管道逻辑:

上面的管道代码适用于这个变量(它是一个单一的对象):

filterVar = {bike: "Electric", country : "FR"};

然后列表中将显示与他们的自行车领域为“电动”和国家与“FR”相匹配的比赛对象

但是当涉及到使用多个对象然后有可能的第二个对象列表来过滤时,事情可能会变得有点复杂,我现在不知道从哪里开始。

关于如何实现此过滤器功能的任何想法?

更新 #1
在尝试实现 Kinglish 的工作解决方案后(它确实有效,运行下面的代码 sn-p 进行测试),我觉得挑战可能是尝试在 typescript 中实现过滤器逻辑?这里我写了下面的函数,但是它返回 0 个结果:

private filterTable(list : any[],filter : Object){
    console.log('------ the list: ', list)
    console.log('------ with filter: ', filter)
    let thefilter = Object.entries(filter);
    const result = list.filter(item => {
      let c = 0;
      // can only return true if each condition passes
      thefilter.length === 0 || thefilter
        .map(([key, val]) => {
          if (!Array.isArray(val)) val = [val]
          c += val.filter(v => {
            return item[key] === v;
          }).length;
        })
      return c >= thefilter.length
    })
    console.log('Found ' + result.length + ' results: ', result)
}

为了测试,我在 ngOnInit() 函数中调用了以下代码:

public ngOnInit(){
    let filter = {
        bikes: ["Mountain", "Electric"],
        countries: "FR"
    }
    this.competitions= CompetitionsData.competitions; //Our competitions.data
    console.log(this.competitions);
    this.filterTable(this.competitions,filter) 
}

但是我们仍然在控制台中收到:

(4) [{…}, {…}, {…}, {…}]
------ the list:  (4) [{…}, {…}, {…}, {…}]
------ with filter:  {bikes: Array(2), countries: "FR"} 
Found 0 results:  []

也许我在这里错误地使用了打字稿?

【问题讨论】:

  • 我发布了,然后意识到它需要工作。现在可以测试了。
  • 这里的错字:ComeptitionsData
  • filterTable(list : any[],filter: any)filterTable(list : any[],filter: object)(小写的 o)——其中任何一个都有效吗?

标签: angular typescript filter angular-pipe


【解决方案1】:

这应该可以解决问题。您必须对其进行一些修改以适应您的逻辑(因为我必须在这里进行测试)。但它会起作用。您可以看到它如何接受过滤器参数(允许使用数组)。试一试,让我知道它是否适合你。

const items = [{
    'id': '0luT3vVGeS',
    'index': 1,
    'isActive': true,
    'title': 'Scotland Mountain Tour',
    'host': 'Scotland Cycles',
    'bike': 'Mountain',
    'country': 'GB',
    'prizePoolTotal': 500000,
    'date': "Sat May 29 2021 11:00",
    'timezone': 'GMT',
    'totalSpaces': 3000,
    'availableSpaces': 1500
  },
  {
    'id': '5lOu8vIUeG',
    'index': 2,
    'isActive': true,
    'title': 'South France Electric',
    'host': 'FR Electric',
    'bike': 'Electric',
    'country': 'FR',
    'prizePoolTotal': 57000,
    'date': "Sat May 29 2021 11:00",
    'timezone': 'GMT',
    'totalSpaces': 300,
    'availableSpaces': 200
  },
  {
    'id': '5lOddu8vIUeG',
    'index': 2,
    'isActive': true,
    'title': 'South France Electric',
    'host': 'FR Electric',
    'bike': 'Electric',
    'country': 'USA',
    'prizePoolTotal': 57000,
    'date': "Sat May 29 2021 11:00",
    'timezone': 'GMT',
    'totalSpaces': 300,
    'availableSpaces': 200
  },
  {
    'id': '5lOddu899vIUeG',
    'index': 2,
    'isActive': true,
    'title': 'South France Electric',
    'host': 'FR Electric',
    'bike': 'Mountain',
    'country': 'CZ',
    'prizePoolTotal': 57000,
    'date': "Sat May 29 2021 11:00",
    'timezone': 'GMT',
    'totalSpaces': 300,
    'availableSpaces': 200
  }
]

// test function
const testFilter = (filter) => {
  console.log('------ with filter: ', filter)

  let thefilter = Object.entries(filter);
  const result = items.filter(item => {
    let c = 0;
    // can only return true if each condition passes
    thefilter.length === 0 || thefilter
      .map(([key, val]) => {
        if (!Array.isArray(val)) val = [val]
        c += val.filter(v => {
          return item[key] === v;
        }).length;
      })
    return c >= thefilter.length
  })
  console.log('Found ' + result.length + ' results: ', result)
}

// testing

let filter = {
  bike: ["Electric", "Mountain"],
  country: "FR"
}
testFilter(filter)

/* ---------- */

filter = {
  bike: "Mountain"
}
testFilter(filter)

/* ---------- */

filter = {
  bike: "Mountain",
  country: ["FR", "USA", "GB"]
}
testFilter(filter)

/* ---------- */

filter = {}
testFilter(filter)

【讨论】:

  • 感谢您的回复,我已在上面的更新中回复。您的代码肯定有效,但我们几乎就在那里。我想我只需要为打字稿解决这个问题。不过不确定。
  • 相对于您的原始问题,这是(主要)是管道过滤器逻辑的复制/粘贴解决方案,不是吗?
猜你喜欢
  • 1970-01-01
  • 2018-01-17
  • 2020-03-24
  • 1970-01-01
  • 1970-01-01
  • 2015-11-02
  • 2018-03-08
  • 2018-04-28
  • 2021-11-07
相关资源
最近更新 更多