eckig 2 sortieren und filtern

77

In Angularjs 1 können Sie folgendermaßen sortieren und filtern:

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

Aber ich konnte in Angularjs 2.0 keine Beispiele dafür finden. Meine Frage ist, wie man in Angularjs 2.0 sortiert und filtert. Wenn es immer noch nicht unterstützt wird, weiß jemand, wann oder ob es in Angularjs 2.0 aufgenommen wird?

alexsoftware
quelle
Danke, ich werde versuchen, meine eigene Pipe für Filter und Sortierung zu implementieren. Seltsam, dass das Angular-Team beschlossen hat, die Funktion zu entfernen. Ich hoffe, sie werden es zurücksetzen, damit es einfacher zu filtern und zu sortieren ist.
Alexsoftware
Können Sie nicht einfach friendsIhren Komponentencode sortieren ?
Red Cricket

Antworten:

81

Dies wird nicht sofort hinzugefügt, da das Angular-Team möchte, dass Angular 2 minimiert ausgeführt wird. OrderBy hat keine Reflexion mehr, die mit der Minimierung bricht. Lesen Sie die Antwort von Miško Heverey zu diesem Thema.

Ich habe mir die Zeit genommen, eine OrderBy-Pipe zu erstellen, die sowohl ein- als auch mehrdimensionale Arrays unterstützt. Es unterstützt auch die Möglichkeit, nach mehreren Spalten des mehrdimensionalen Arrays zu sortieren.

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

Diese Pipe ermöglicht das Hinzufügen weiterer Elemente zum Array nach dem Rendern der Seite und das korrekte Sortieren der Arrays mit den neuen Elementen.

Ich habe hier einen Bericht über den Prozess .

Und hier ist eine funktionierende Demo: http://fuelinteractive.github.io/fuel-ui/#/pipe/orderby und https://plnkr.co/edit/DHLVc0?p=info

BEARBEITEN: Neue Demo zu http://fuelinteractive.github.io/fuel-ui/#/pipe/orderby hinzugefügt

EDIT 2: ngFor auf neue Syntax aktualisiert

Cory Shaw
quelle
2
Kleines Update. Neueste Angular2 * ngFor würde * ngFor = "Person von Menschen lassen ... anstelle des Hashtags #
Pat M
2
@CoryShaw tolle Pfeife! gut gemacht **** klatschen Emoji *****
Chaos Monkey
1
@invot Richtig, diese Pipe ist nur die orderBy-Funktionalität. Auf dem Array sollte eine zweite Pipe zum Filtern verwendet werden. Die Antwort von select unten ist ein gutes Beispiel für das Filtern
Cory Shaw
2
@ 72GM mehrdimensional wäre eigentlich [][], also sind Sie richtig. Wäre Mehrebenen besser formuliert? [].SomeObjectProperty.SomeProperty
Cory Shaw
1
Ich benutze Angular 6 und habe es innerhalb von ca. 5 Minuten zum Laufen gebracht. Ich habe gerade eine Pipe mit CLI erstellt und dann den Code kopiert und alle kleinen Dinge behoben, die TS-Lint gezeigt hat (nur Flusenfehler), und es hat wie ein Zauber funktioniert. Habe es schon 5 mal in meiner App in der ersten Stunde benutzt - exzellente Pipe!
Alfa Bravo
22

Es wird vom Design nicht unterstützt. Die sortBy-Pipe kann bei einer App im Produktionsmaßstab zu echten Leistungsproblemen führen. Dies war ein Problem mit der eckigen Version 1.

Sie sollten keine benutzerdefinierte Sortierfunktion erstellen. Stattdessen sollten Sie Ihr Array zuerst in der Typoskriptdatei sortieren und dann anzeigen. Wenn die Reihenfolge aktualisiert werden muss, wenn beispielsweise eine Dropdown-Liste ausgewählt ist, muss diese Dropdown-Auswahl eine Funktion auslösen und Ihre von dort aufgerufene Sortierfunktion aufrufen. Diese Sortierfunktion kann in einen Dienst extrahiert werden, damit er wiederverwendet werden kann. Auf diese Weise wird die Sortierung nur angewendet, wenn dies erforderlich ist, und Ihre App-Leistung wird viel besser.

Bäume_sind_groß
quelle
1
Obwohl ich die Gründe dafür verstehe, finde ich es ziemlich frustrierend, solche allgemeinen Funktionen ohne offensichtlichen Ersatz zu verlieren. Natürlich kann ich meine eigene Sortierung usw. implementieren, aber warum gibt es keinen einfachen Ersatz, der für die Verwendung in Diensten anstelle von Vorlagen vorgesehen ist?
Schneida
1
@schneida: Vielleicht, weil es viele andere Bibliotheken gibt, die für Sie sortieren können, wie Sie möchten und mit Kompromissen, die Sie kennen und mit denen Sie leben können? vergleiche dh. warum momentoder moment-timezonenicht standardmäßig enthalten, dass dies eine so häufige Funktion ohne offensichtlichen Ersatz ist (übrigens siehe externes Paket angular2-momentfür entsprechende Pipes für Moment-Dinge - dies zeigt auch, wie einfach es ist, ein Plugin zu erstellen, das die Lücke füllt)
quetzalcoatl
Die Sortier- und Filterlogik von Imho gehört zu Ihren Store-Selektoren (wenn Sie Redux / RxJS oder ähnliche Muster verwenden).
Spock
18

Hier ist eine einfache Filterpipe für ein Array von Objekten, die Attribute mit Zeichenfolgenwerten enthalten (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;
          }
        }
      });
    }
  }
}

Ihre Komponente

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 = '';
  }
}

In Ihrer Vorlage

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>
wählen
quelle
Die Dateien sehen sehr ähnlich aus, wie das Typoskript geschrieben werden würde. Sind die Dateien tatsächlich .ts?
Alex J
Sie sind kein Typepscript, Sie müssten Typen in den Funktionsheadern transform(value: ..., args: ...)und bei den Variablendeklarationen mit hinzufügen let.
Wählen Sie
Bei Verwendung mit Node wird jedoch ein Fehler beim Filer ausgegeben: Abfrage des JSON-Objekts. Sie wissen, warum dieser Fehler kommt?
Jignesh Vagh
1
@JigneshVagh filterist eine Array-Funktion, daher funktioniert dies nur für Objektlisten und nicht für Objekte selbst. Ich hoffe, dies hilft.
wählen
13

Eine Pipe nimmt Daten als Eingabe auf und wandelt sie in eine gewünschte Ausgabe um. Fügen Sie diese Pipe-Datei hinzu: orderby.tsin Ihrem /appOrdner.

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;
    }
    //
  }
}

Importieren Sie in Ihre Komponentendatei (app.component.ts) die gerade hinzugefügte Pipe mit: import {OrderByPipe} from './orderby';

Fügen Sie dann *ngFor="#article of articles | orderby:'id'"in Ihre Vorlage ein, wenn Sie Ihre Artikel nach ID in aufsteigender oder orderby:'!id'"absteigender Reihenfolge sortieren möchten .

Wir fügen einer Pipe Parameter hinzu, indem wir dem Pipe-Namen einen Doppelpunkt (:) und dann den Parameterwert folgen

Wir müssen unsere Pipe im Pipes-Array des @ Component-Dekorators auflisten. 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",
        }]  
    }

}

Mehr Infos hier auf meinem Github und diesen Beitrag auf meiner Website

Nicolas2bert
quelle
1
Bitte posten Sie keine doppelten Antworten . Ziehen Sie stattdessen andere Aktionen in Betracht, die zukünftigen Benutzern helfen könnten, die Antwort zu finden, die sie benötigen, wie im verlinkten Beitrag beschrieben. Insbesondere, wenn der Beitrag Links zu Ihrer Website enthält, da diese Beiträge als Spam erscheinen.
Mogsdad
Lesen Sie in diesem Zusammenhang bitte Wie man persönliche Open-Source-Bibliotheken anbietet. auch.
Martijn Pieters
OK Leute @Mogsdad - Tut mir leid, hoffe es hilft übrigens!
Nicolas2bert
4
Mir hat gefallen, wie das strukturiert und leicht zu verstehen ist. Vielen Dank. ABER, aktualisieren Sie bitte Ihr Skript hier UND auf Ihrer Website / Ihrem Github. Ändern Sie in der ersten Zeile "angle2 / core" in "@ angle / core". Außerdem konnte ich es zu Beginn nicht zum Laufen bringen, dann flog ich durch Ihren Code und stellte fest, dass Ihr "Vorlagen" -Schritt einen großen Tippfehler hat. In der Vorlage muss es ein Array sein, damit alles wie beabsichtigt funktioniert: "| orderby: ['id']"
Starwave
1
@Starwave +1 für die Erwähnung des Fehlers in der Vorlage. Sehr geschätzt.
Gary
4

Sie müssen Ihre eigene Pipe für die Arraysortierung erstellen. Hier ist ein Beispiel, wie Sie dies tun können.

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

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

Vlado Tesanovic
quelle
10
Warum bieten sie dies nicht sofort an? Es ist so üblich, dass es lächerlich ist, dass sie das nicht bieten.
Bersling
Ich denke auch, dass es ein Problem in Ihrer Implementierung gibt, es funktioniert mit '-date', aber wenn Sie nur 'date' schreiben würden, let column = args[0].slice(1);macht der Befehl die Spalte so, atedass sie offensichtlich kein gültiger Schlüssel mehr ist.
Bersling
1
@bersling ihre Argumentation ist, dass sie wollen, dass Angular 2 minimiert werden kann und trotzdem korrekt funktioniert. OrderBy erfordert Reflexion, die nicht minimiert werden kann
Cory Shaw
2
Das macht keinen Sinn ... alle oben genannten Lösungen können minimiert werden, nicht wahr? Wie kann ein so wichtiges Framework solche grundlegenden Funktionen weglassen ...
Kokodoko
1

Das ist meine Art. Es wird die Sortierung von Zahlen, Zeichenfolgen und Datumsangaben durchführen.

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;

  }

}
Menschliches Wesen
quelle