【问题标题】:angular 2 sort and filter角度2排序和过滤
【发布时间】:2015-10-01 07:41:13
【问题描述】:

在 Angularjs 1 中可以通过以下方式进行排序和过滤:

<ul ng-repeat="friend in friends | filter:query | orderBy: 'name' ">
   <li>{{friend.name}}</li>
</ul>

但我找不到任何关于如何在 Angularjs 2.0 中执行此操作的示例。我的问题是如何在 Angularjs 2.0 中进行排序和过滤?如果仍然不支持,有谁知道它何时或是否会被放入 Angularjs 2.0 中?

【问题讨论】:

标签: angular typescript


【解决方案1】:

这不是开箱即用的,因为 Angular 团队希望 Angular 2 能够以最小化的方式运行。 OrderBy 没有反射,反射会随着缩小而中断。请查看Miško Heverey's response 了解此事。

我花时间创建了一个支持单维和多维数组的 OrderBy 管道。它还支持对多维数组的多个列进行排序。

<li *ngFor="let person of people | orderBy : ['-lastName', 'age']">{{person.firstName}} {{person.lastName}}, {{person.age}}</li>

此管道确实允许在呈现页面后向数组添加更多项,并且仍然使用新项正确地对数组进行排序。

我有一个write up on the process here

这是一个工作演示:http://fuelinteractive.github.io/fuel-ui/#/pipe/orderbyhttps://plnkr.co/edit/DHLVc0?p=info

编辑:向http://fuelinteractive.github.io/fuel-ui/#/pipe/orderby添加了新的演示

编辑 2:将 ngFor 更新为新语法

【讨论】:

  • 小更新。最新的 Angular2 *ngFor 将使用 *ngFor="let person of people... 而不是标签 #
  • @CoryShaw 很棒的管道!干得好****拍手表情*****
  • @invot 正确,这个管道只是 orderBy 功能。应在阵列上使用第二个管道进行过滤。 select下面的答案是过滤的一个很好的例子
  • @72GM 多维实际上是[][],所以你是对的。多层次会是更好的措辞吗? [].SomeObjectProperty.SomeProperty
  • 我正在使用 Angular 6 并在大约 5 分钟内让它工作。刚刚使用 CLI 创建了一个管道,然后复制了代码并修复了 TS-Lint 显示的所有小问题(只是 lint 错误),它就像一个魅力。在第一个小时内,我的应用程序中已经使用了 5 次 - 很棒的管道!
【解决方案2】:

设计不支持。 sortBy 管道可能会导致生产规模应用程序的实际性能问题。这是 Angular 版本 1 的问题。

您不应创建自定义排序函数。相反,您应该首先在 typescript 文件中对数组进行排序,然后再显示它。如果在选择下拉列表时需要更新订单,则让此下拉选择触发一个函数并调用从中调用的排序函数。可以将此排序功能提取到服务中,以便可以重新使用它。这样,排序只会在需要时应用,您的应用程序性能会更好。

【讨论】:

  • 虽然我确实理解这背后的原因,但我会发现在没有明显替换的情况下松散诸如通用功能之类的功能非常令人沮丧。当然我可以实现自己的排序等,但为什么没有简单的替代品用于服务而不是模板。
  • @schneida:也许是因为有很多其他的库可以为你进行排序,以你喜欢的方式,以及你知道并且可以忍受的权衡?比较即。为什么默认不包含momentmoment-timezone,这是一个没有明显替换的常见功能(顺便说一句。请参阅外部包angular2-moment 以获取相应的管道以获取瞬间的东西 - 这也表明做一个是多么容易填补空白的插件)
  • 恕我直言,排序和过滤逻辑属于您的商店选择器(如果您使用 Redux/RxJS 或其他类似的模式)。
【解决方案3】:

这是一个简单的过滤器管道,用于包含带有字符串值的属性的对象数组(ES6)

filter-array-pipe.js

import {Pipe} from 'angular2/core';

// # Filter Array of Objects
@Pipe({ name: 'filter' })
export class FilterArrayPipe {
  transform(value, args) {
    if (!args[0]) {
      return value;
    } else if (value) {
      return value.filter(item => {
        for (let key in item) {
          if ((typeof item[key] === 'string' || item[key] instanceof String) && 
              (item[key].indexOf(args[0]) !== -1)) {
            return true;
          }
        }
      });
    }
  }
}

你的组件

myobjComponent.js

import {Component} from 'angular2/core';
import {HTTP_PROVIDERS, Http} from 'angular2/http';
import {FilterArrayPipe} from 'filter-array-pipe';

@Component({
  templateUrl: 'myobj.list.html',
  providers: [HTTP_PROVIDERS],
  pipes: [FilterArrayPipe]
})
export class MyObjList {
  static get parameters() {
    return [[Http]];
  }
  constructor(_http) {
    _http.get('/api/myobj')
      .map(res => res.json())
      .subscribe(
        data => this.myobjs = data,
        err => this.logError(err))
      );
  }
  resetQuery(){
    this.query = '';
  }
}

在您的模板中

myobj.list.html

<input type="text" [(ngModel)]="query" placeholder="... filter" > 
<div (click)="resetQuery()"> <span class="icon-cross"></span> </div>
</div>
<ul><li *ngFor="#myobj of myobjs| filter:query">...<li></ul>

【讨论】:

  • 这些文件看起来与打字稿的编写方式非常相似。这些文件实际上是 .ts 吗?
  • 它们不是 Typepscript,您必须在函数头 transform(value: ..., args: ...) 和带有 let 的变量声明中添加类型。
  • 但是当与节点一起使用时,它会在 filer 上给出错误:json 对象上的查询。你知道为什么会出现这个错误吗?
  • @JigneshVagh filter 是一个数组函数,所以这只适用于对象列表而不是对象本身,希望对您有所帮助。
【解决方案4】:

管道将数据作为输入并将其转换为所需的输出。 将此管道文件:orderby.ts 添加到您的 /app 文件夹中。

orderby.ts

//The pipe class implements the PipeTransform interface's transform method that accepts an input value and an optional array of parameters and returns the transformed value.

import { Pipe,PipeTransform } from "angular2/core";

//We tell Angular that this is a pipe by applying the @Pipe decorator which we import from the core Angular library.

@Pipe({

  //The @Pipe decorator takes an object with a name property whose value is the pipe name that we'll use within a template expression. It must be a valid JavaScript identifier. Our pipe's name is orderby.

  name: "orderby"
})

export class OrderByPipe implements PipeTransform {
  transform(array:Array<any>, args?) {

    // Check if array exists, in this case array contains articles and args is an array that has 1 element : !id

    if(array) {

      // get the first element

      let orderByValue = args[0]
      let byVal = 1

      // check if exclamation point 

      if(orderByValue.charAt(0) == "!") {

        // reverse the array

        byVal = -1
        orderByValue = orderByValue.substring(1)
      }
      console.log("byVal",byVal);
      console.log("orderByValue",orderByValue);

      array.sort((a: any, b: any) => {
        if(a[orderByValue] < b[orderByValue]) {
          return -1*byVal;
        } else if (a[orderByValue] > b[orderByValue]) {
          return 1*byVal;
        } else {
          return 0;
        }
      });
      return array;
    }
    //
  }
}

在您的组件文件 (app.component.ts) 中导入您刚刚添加的管道:import {OrderByPipe} from './orderby';

然后,如果您想按 id 升序或orderby:'!id'" 降序对文章进行排序,请在模板中添加 *ngFor="#article of articles | orderby:'id'"

我们通过在管道名称后跟一个冒号(:)然后是参数值来向管道添加参数

我们必须在 @Component 装饰器的管道数组中列出我们的管道。 pipes: [ OrderByPipe ]

app.component.ts

import {Component, OnInit} from 'angular2/core';
import {OrderByPipe} from './orderby';

@Component({
    selector: 'my-app',
    template: `
      <h2>orderby-pipe by N2B</h2>
      <p *ngFor="#article of articles | orderby:'id'">
        Article title : {{article.title}}
      </p>
    `,
    pipes: [ OrderByPipe ]

})
export class AppComponent{
    articles:Array<any>
    ngOnInit(){
        this.articles = [
        {
            id: 1,
            title: "title1"
        },{
            id: 2,
            title: "title2",
        }]  
    }

}

更多信息here on my githubthis post on my website

【讨论】:

  • 请不要发帖duplicate answers。相反,请考虑其他可以帮助未来用户找到所需答案的操作,如链接帖子中所述。尤其是当帖子包含指向您网站的链接时,因为这些帖子开始显示为垃圾内容。
  • 在这种情况下,也请阅读How to offer personal open-source libraries?
  • 好的,伙计们@Mogsdad - 很抱歉,希望对您有所帮助!
  • 我喜欢这种结构方式,易于理解。谢谢你。但是,请在此处和您的网站/github 上更新您的脚本。在第一行将“angular2/core”更改为“@angular/core”。除此之外,一开始我无法让它工作,然后我浏览了你的代码并意识到你的“模板”步骤有一个很大的错字。在模板中,它必须是一个数组,一切才能按预期工作:“| orderby:['id']”
  • @Starwave +1 用于提及模板中的错误。非常感谢。
【解决方案5】:

您必须为数组排序创建自己的管道,这是一个示例。

<li *ngFor="#item of array | arraySort:'-date'">{{item.name}} {{item.date | date:'medium' }}</li>

https://plnkr.co/edit/DU6pxr?p=preview

【讨论】:

  • 他们为什么不提供这个开箱即用?这是很常见的事情,他们不提供这很荒谬。
  • 另外我认为你的实现中存在问题,它适用于'-date',但如果你只写'date',let column = args[0].slice(1); 命令使列只是ate,即显然不再是有效的密钥了。
  • @bersling 他们的理由是他们希望 Angular 2 能够被缩小并且仍然可以正常工作。 OrderBy 需要无法缩小的反射
  • 这没有意义......上述所有解决方案都可以缩小,不是吗?这么大的框架怎么会省略这么基本的功能……
【解决方案6】:

这是我喜欢的。它将进行数字排序、字符串排序和日期排序。

import { Pipe , PipeTransform  } from "@angular/core";

@Pipe({
  name: 'sortPipe'
 })

export class SortPipe implements PipeTransform {

    transform(array: Array<string>, key: string): Array<string> {

        console.log("Entered in pipe*******  "+ key);


        if(key === undefined || key == '' ){
            return array;
        }

        var arr = key.split("-");
        var keyString = arr[0];   // string or column name to sort(name or age or date)
        var sortOrder = arr[1];   // asc or desc order
        var byVal = 1;


        array.sort((a: any, b: any) => {

            if(keyString === 'date' ){

                let left    = Number(new Date(a[keyString]));
                let right   = Number(new Date(b[keyString]));

                return (sortOrder === "asc") ? right - left : left - right;
            }
            else if(keyString === 'name'){

                if(a[keyString] < b[keyString]) {
                    return (sortOrder === "asc" ) ? -1*byVal : 1*byVal;
                } else if (a[keyString] > b[keyString]) {
                    return (sortOrder === "asc" ) ? 1*byVal : -1*byVal;
                } else {
                    return 0;
                }  
            }
            else if(keyString === 'age'){
                return (sortOrder === "asc") ? a[keyString] - b[keyString] : b[keyString] - a[keyString];
            }

        });

        return array;

  }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-22
    • 1970-01-01
    • 2013-11-13
    • 2020-07-28
    相关资源
    最近更新 更多