web-dev-qa-db-fra.com

Angular 2 OrderBy Pipe

Je ne suis pas en mesure de traduire ce code d'angualr1 en angular2, aucune aide?

ng-repeat="todo in todos | orderBy: 'completed'"

Voici ce que j'ai fait en suivant la réponse de Thierry Templier:

modèle html:

*ngFor="#todo of todos | sort"

fichier de composant:

@Component({
    selector: 'my-app',
    templateUrl: "./app/todo-list.component.html",
    providers: [TodoService],
    pipes: [ TodosSortPipe ]

})

fichier pipe:

import { Pipe } from "angular2/core";
import {Todo} from './todo';

@Pipe({
  name: "sort"
})
export class TodosSortPipe {
  transform(array: Array<Todo>, args: string): Array<Todo> {
    array.sort((a: any, b: any) => {
      if (a < b) {
        return -1;
      } else if (a > b) {
        return 1;
      } else {
        return 0;
      }
    });
    return array;
  }
}

Je suis sûr que l'erreur est dans le @Pipe, im essayant de trier un tableau de Todos, ordonné par la propriété todo.completed. Tout d'abord todo.completed = false et que todo.complete = true.

Je suis honnête, je n'ai pas très bien compris la méthode de transformation et comment passer les arguments dans cette méthode et dans la méthode de tri.

Comme, quel est l'argument args: string? a et b, quels sont-ils? d'où ils viennent?

73
user4956851

Veuillez consulter https://angular.io/guide/pipes#appendix-no-filterpipe-or- orderbypipe pour une discussion complète. Cette citation est la plus pertinente… .. Fondamentalement, pour les applications à grande échelle qui doivent être minimisées de manière agressive, la logique de filtrage et de tri doit passer au composant lui-même.

"Certains d'entre nous ne voudront peut-être pas minimiser cela de manière agressive. C'est notre choix Mais le produit angulaire ne devrait pas empêcher quelqu'un d'autre de Minifier de manière agressive. Par conséquent, l'équipe angulaire a décidé que Tout ce qui est expédié dans Angular sera Minify en toute sécurité.

L'équipe angulaire et de nombreux développeurs expérimentés ont fortement Il est recommandé de déplacer la logique de filtrage et de tri dans le composant lui-même. Le composant peut exposer un filtre filtré ou des filtres triés propriété et prendre le contrôle de quand et à quelle fréquence exécuter le logique de soutien. Toutes les capacités que vous auriez mises dans un tuyau et partagés à travers l'application peuvent être écrits dans un filtrage/tri service et injecté dans le composant ".

56
Vitali Kniazeu

J'ai modifié la réponse de @Thierry Templier afin que le tuyau puisse trier des objets personnalisés dans angular 4:

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

@Pipe({
  name: "sort"
})
export class ArraySortPipe  implements PipeTransform {
  transform(array: any, field: string): any[] {
    if (!Array.isArray(array)) {
      return;
    }
    array.sort((a: any, b: any) => {
      if (a[field] < b[field]) {
        return -1;
      } else if (a[field] > b[field]) {
        return 1;
      } else {
        return 0;
      }
    });
    return array;
  }
}

Et pour l'utiliser:

*ngFor="let myObj of myArr | sort:'fieldName'"

Espérons que cela aide quelqu'un.

45
Sal

Vous pouvez implémenter pour cela un canal personnalisé qui exploite la méthode sort de tableaux:

import { Pipe } from "angular2/core";

@Pipe({
  name: "sort"
})
export class ArraySortPipe {
  transform(array: Array<string>, args: string): Array<string> {
    array.sort((a: any, b: any) => {
      if (a < b) {
        return -1;
      } else if (a > b) {
        return 1;
      } else {
        return 0;
      }
    });
    return array;
  }
}

Et utilisez ensuite ce tuyau comme décrit ci-dessous. N'oubliez pas de spécifier votre canal dans l'attribut pipes du composant:

@Component({
  (...)
  template: `
    <li *ngFor="list | sort"> (...) </li>
  `,
  pipes: [ ArraySortPipe ]
})
(...)

C'est un exemple simple pour les tableaux avec des valeurs de chaîne, mais vous pouvez avoir un traitement de tri avancé (basé sur des attributs d'objet dans le cas d'un tableau d'objets, basé sur des paramètres de tri, ...).

Voici un plunkr pour ceci: https://plnkr.co/edit/WbzqDDOqN1oAhvqMkQRQ?p=preview .

J'espère que ça vous aide, Thierry

35
Thierry Templier

Angular ne vient pas avec un filtre orderBy, mais si nous en décidons, nous en avons besoin, nous pouvons facilement en créer un. Nous devons toutefois tenir compte de certaines mises en garde concernant la vitesse et la minification. Voir ci-dessous.

Un simple tuyau ressemblerait à quelque chose comme ça.

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

@Pipe({
  name: 'sort'
})
export class SortPipe implements PipeTransform {
  transform(ary: any, fn: Function = (a,b) => a > b ? 1 : -1): any {
    return ary.sort(fn)
  }
}

Ce canal accepte une fonction de tri (fn) et lui donne une valeur par défaut permettant de trier un tableau de primitives de manière judicieuse. Nous avons la possibilité de remplacer cette fonction de tri si nous le souhaitons.

Il n'accepte pas un nom d'attribut en tant que chaîne, car les noms d'attribut sont sujets à une minification. Ils changeront lorsque nous réduirons notre code, mais les minificateurs ne sont pas assez intelligents pour minimiser également la valeur dans la chaîne de modèle.

Tri des primitives (nombres et chaînes)

Nous pourrions utiliser ceci pour trier un tableau de nombres ou de chaînes en utilisant le comparateur par défaut:

import { Component } from '@angular/core';

@Component({
  selector: 'cat',
  template: `
    {{numbers | sort}}
    {{strings | sort}}
  `
})
export class CatComponent
  numbers:Array<number> = [1,7,5,6]
  stringsArray<string> = ['cats', 'hats', 'caveats']
}

Tri d'un tableau d'objets

Si nous voulons trier un tableau d'objets, nous pouvons lui donner une fonction de comparaison.

import { Component } from '@angular/core';

@Component({
  selector: 'cat',
  template: `
    {{cats | sort:byName}}
  `
})
export class CatComponent
  cats:Array<Cat> = [
    {name: "Missy"},
    {name: "Squoodles"},
    {name: "Madame Pompadomme"}
  ]
  byName(a,b) {
    return a.name > b.name ? 1 : -1
  }
}

Mises en garde - pipes pures et impures

Angular 2 a un concept de tuyaux purs et impurs. 

Un tuyau pur optimise la détection des modifications à l'aide de l'identité de l'objet. Cela signifie que le tube ne sera exécuté que si l'objet en entrée change d'identité, par exemple si nous ajoutons un nouvel élément au tableau. Il ne descendra pas dans les objets. Cela signifie que si nous modifions un attribut imbriqué: this.cats[2].name = "Fluffy" par exemple, le canal ne sera pas réexécuté. Cela aide Angular à être rapide. Les pipes angulaires sont pures par défaut.

Un tuyau impur vérifie par contre les attributs de l'objet. Cela le rend potentiellement beaucoup plus lent. Parce qu'il ne peut pas garantir ce que fera la fonction pipe (peut-être qu'elle sera différente selon l'heure du jour, par exemple), un pipe impur sera exécuté chaque fois qu'un événement asynchrone se produira. Ceci ralentira votre app considérablement si le tableau est grand.

La pipe ci-dessus est pure. Cela signifie qu'il ne s'exécutera que lorsque les objets du tableau seront immuables. Si vous changez de chat, vous devez remplacer l'objet chat entier par un nouveau.

this.cats[2] = {name:"Tomy"}

Nous pouvons changer ce qui précède en un tuyau impur en définissant l'attribut pur:

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

@Pipe({
  name: 'sort',
  pure: false
})
export class SortPipe implements PipeTransform {
  transform(ary: any, fn: Function = (a,b) => a > b ? 1 : -1): any {
    return ary.sort(fn)
  }
}

Ce tuyau descendra dans les objets, mais sera plus lent. Utiliser avec précaution.

8
superluminary

J'ai créé un tuyau OrderBy qui répond exactement à vos besoins. Il prend également en charge la possibilité de trier sur plusieurs colonnes d’un objet énumérable.

<li *ngFor="#todo in todos | orderBy : ['completed']">{{todo.name}} {{todo.completed}}</li>

Ce canal permet d’ajouter plus d’éléments au tableau après le rendu de la page et triera le tableau avec les mises à jour de manière dynamique.

J'ai un écrire sur le processus ici .

Et voici une démo de travail: http://fuelinteractive.github.io/fuel-ui/#/pipe/orderby et https://plnkr.co/edit/DHLVc0?p=info

7
Cory Shaw

OrderByPipe mis à jour: correction du tri des chaînes.

créer une classe OrderByPipe:

import { Pipe, PipeTransform } from "@angular/core";
@Pipe( {
name: 'orderBy'
} )
export class OrderByPipe implements PipeTransform {
transform( array: Array<any>, orderField: string, orderType: boolean ): Array<string> {
    array.sort( ( a: any, b: any ) => {
        let ae = a[ orderField ];
        let be = b[ orderField ];
        if ( ae == undefined && be == undefined ) return 0;
        if ( ae == undefined && be != undefined ) return orderType ? 1 : -1;
        if ( ae != undefined && be == undefined ) return orderType ? -1 : 1;
        if ( ae == be ) return 0;
        return orderType ? (ae.toString().toLowerCase() > be.toString().toLowerCase() ? -1 : 1) : (be.toString().toLowerCase() > ae.toString().toLowerCase() ? -1 : 1);
    } );
    return array;
  }
}

dans votre contrôleur: 

@Component({
pipes: [OrderByPipe]
})

ou dans votre

 declarations: [OrderByPipe]

dans votre html:

<tr *ngFor="let obj of objects | orderBy : ObjFieldName: OrderByType">

ObjFieldName: nom du champ d'objet que vous souhaitez trier;

OrderByType: booléen; vrai: ordre décroissant; faux: ascendant;

7
GuoJunjun

Cela fonctionnera pour tous les champs que vous y passerez. ( IMPORTANT: Il ne s’agit que par ordre alphabétique, donc si vous transmettez une date, il sera classé en ordre alphabétique et non en date)

/*
 *      Example use
 *      Basic Array of single type: *ngFor="let todo of todoService.todos | orderBy : '-'"
 *      Multidimensional Array Sort on single column: *ngFor="let todo of todoService.todos | orderBy : ['-status']"
 *      Multidimensional Array Sort on multiple columns: *ngFor="let todo of todoService.todos | orderBy : ['status', '-title']"
 */

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

@Pipe({name: "orderBy", pure: false})
export class OrderByPipe implements PipeTransform {

    value: string[] = [];

    static _orderByComparator(a: any, b: any): number {

        if (a === null || typeof a === "undefined") { a = 0; }
        if (b === null || typeof b === "undefined") { b = 0; }

        if (
            (isNaN(parseFloat(a)) ||
            !isFinite(a)) ||
            (isNaN(parseFloat(b)) || !isFinite(b))
        ) {
            // Isn"t a number so lowercase the string to properly compare
            a = a.toString();
            b = b.toString();
            if (a.toLowerCase() < b.toLowerCase()) { return -1; }
            if (a.toLowerCase() > b.toLowerCase()) { return 1; }
        } else {
            // Parse strings as numbers to compare properly
            if (parseFloat(a) < parseFloat(b)) { return -1; }
            if (parseFloat(a) > parseFloat(b)) { return 1; }
        }

        return 0; // equal each other
    }

    public transform(input: any, config = "+"): any {
        if (!input) { return input; }

        // make a copy of the input"s reference
        this.value = [...input];
        let value = this.value;
        if (!Array.isArray(value)) { return value; }

        if (!Array.isArray(config) || (Array.isArray(config) && config.length === 1)) {
            let propertyToCheck: string = !Array.isArray(config) ? config : config[0];
            let desc = propertyToCheck.substr(0, 1) === "-";

            // Basic array
            if (!propertyToCheck || propertyToCheck === "-" || propertyToCheck === "+") {
                return !desc ? value.sort() : value.sort().reverse();
            } else {
                let property: string = propertyToCheck.substr(0, 1) === "+" || propertyToCheck.substr(0, 1) === "-"
                    ? propertyToCheck.substr(1)
                    : propertyToCheck;

                return value.sort(function(a: any, b: any) {
                    let aValue = a[property];
                    let bValue = b[property];

                    let propertySplit = property.split(".");

                    if (typeof aValue === "undefined" && typeof bValue === "undefined" && propertySplit.length > 1) {
                        aValue = a;
                        bValue = b;
                        for (let j = 0; j < propertySplit.length; j++) {
                            aValue = aValue[propertySplit[j]];
                            bValue = bValue[propertySplit[j]];
                        }
                    }

                    return !desc
                        ? OrderByPipe._orderByComparator(aValue, bValue)
                        : -OrderByPipe._orderByComparator(aValue, bValue);
                });
            }
        } else {
            // Loop over property of the array in order and sort
            return value.sort(function(a: any, b: any) {
                for (let i = 0; i < config.length; i++) {
                    let desc = config[i].substr(0, 1) === "-";
                    let property = config[i].substr(0, 1) === "+" || config[i].substr(0, 1) === "-"
                        ? config[i].substr(1)
                        : config[i];

                    let aValue = a[property];
                    let bValue = b[property];

                    let propertySplit = property.split(".");

                    if (typeof aValue === "undefined" && typeof bValue === "undefined" && propertySplit.length > 1) {
                        aValue = a;
                        bValue = b;
                        for (let j = 0; j < propertySplit.length; j++) {
                            aValue = aValue[propertySplit[j]];
                            bValue = bValue[propertySplit[j]];
                        }
                    }

                    let comparison = !desc
                        ? OrderByPipe._orderByComparator(aValue, bValue)
                        : -OrderByPipe._orderByComparator(aValue, bValue);

                    // Don"t return 0 yet in case of needing to sort by next property
                    if (comparison !== 0) { return comparison; }
                }

                return 0; // equal each other
            });
        }
    }
}
3
CommonSenseCode

Recommandez-vous d'utiliser lodash avec un angle, votre pipe sera ensuite

import {Pipe, PipeTransform} from '@angular/core';
import * as _ from 'lodash'
@Pipe({
    name: 'orderBy'
})
export class OrderByPipe implements PipeTransform {

    transform(array: Array<any>, args?: any): any {
        return _.sortBy(array, [args]);
    }

}

et l'utiliser en HTML comme

*ngFor = "#todo of todos | orderBy:'completed'"

et n'oubliez pas d'ajouter Pipe à votre module

@NgModule({
    ...,
    declarations: [OrderByPipe, ...],
    ...
})

C'est un bon remplacement pour AngularJs orderby pipe dans angular 4. Facile et simple à utiliser.

Ceci est l'URL de github pour plus d'informations https://github.com/VadimDez/ngx-order-pipe

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

@Pipe({
  name: 'orderBy'
})
export class OrderPipe implements PipeTransform {

  transform(value: any | any[], expression?: any, reverse?: boolean): any {
    if (!value) {
      return value;
    }

    const isArray = value instanceof Array;

    if (isArray) {
      return this.sortArray(value, expression, reverse);
    }

    if (typeof value === 'object') {
      return this.transformObject(value, expression, reverse);
    }

    return value;
  }

  /**
   * Sort array
   *
   * @param value
   * @param expression
   * @param reverse
   * @returns {any[]}
   */
  private sortArray(value: any[], expression?: any, reverse?: boolean): any[] {
    const isDeepLink = expression && expression.indexOf('.') !== -1;

    if (isDeepLink) {
      expression = OrderPipe.parseExpression(expression);
    }

    let array: any[] = value.sort((a: any, b: any): number => {
      if (!expression) {
        return a > b ? 1 : -1;
      }

      if (!isDeepLink) {
        return a[expression] > b[expression] ? 1 : -1;
      }

      return OrderPipe.getValue(a, expression) > OrderPipe.getValue(b, expression) ? 1 : -1;
    });

    if (reverse) {
      return array.reverse();
    }

    return array;
  }


  /**
   * Transform Object
   *
   * @param value
   * @param expression
   * @param reverse
   * @returns {any[]}
   */
  private transformObject(value: any | any[], expression?: any, reverse?: boolean): any {
    let parsedExpression = OrderPipe.parseExpression(expression);
    let lastPredicate = parsedExpression.pop();
    let oldValue = OrderPipe.getValue(value, parsedExpression);

    if (!(oldValue instanceof Array)) {
      parsedExpression.Push(lastPredicate);
      lastPredicate = null;
      oldValue = OrderPipe.getValue(value, parsedExpression);
    }

    if (!oldValue) {
      return value;
    }

    const newValue = this.transform(oldValue, lastPredicate, reverse);
    OrderPipe.setValue(value, newValue, parsedExpression);
    return value;
  }

  /**
   * Parse expression, split into items
   * @param expression
   * @returns {string[]}
   */
  private static parseExpression(expression: string): string[] {
    expression = expression.replace(/\[(\w+)\]/g, '.$1');
    expression = expression.replace(/^\./, '');
    return expression.split('.');
  }

  /**
   * Get value by expression
   *
   * @param object
   * @param expression
   * @returns {any}
   */
  private static getValue(object: any, expression: string[]) {
    for (let i = 0, n = expression.length; i < n; ++i) {
      const k = expression[i];
      if (!(k in object)) {
        return;
      }
      object = object[k];
    }

    return object;
  }

  /**
   * Set value by expression
   *
   * @param object
   * @param value
   * @param expression
   */
  private static setValue(object: any, value: any, expression: string[]) {
    let i;
    for (i = 0; i < expression.length - 1; i++) {
      object = object[expression[i]];
    }

    object[expression[i]] = value;
  }
}
3
ganesh kalje

Comme nous savons que filter et order by sont supprimés de ANGULAR 2 et que nous devons écrire les nôtres, voici un bon exemple sur plunker et article détaillé

Il utilisait à la fois filtre et orderby, voici le code pour le pipe de commande

import { Pipe, PipeTransform } from '@angular/core';    
@Pipe({  name: 'orderBy' })
export class OrderrByPipe implements PipeTransform {

  transform(records: Array<any>, args?: any): any {       
    return records.sort(function(a, b){
          if(a[args.property] < b[args.property]){
            return -1 * args.direction;
          }
          else if( a[args.property] > b[args.property]){
            return 1 * args.direction;
          }
          else{
            return 0;
          }
        });
    };
 }
2
Ali Adravi

Dans package.json, ajoutez quelque chose comme:

  "ngx-order-pipe": "^1.1.3",

Dans votre module TypeScript (et tableau d'importations):

  import { OrderModule } from 'ngx-order-pipe';
1

Vous pouvez utiliser ceci pour les objets:

@Pipe({
  name: 'sort',
})
export class SortPipe implements PipeTransform {

  transform(array: any[], field: string): any[] {
    return array.sort((a, b) => a[field].toLowerCase() !== b[field].toLowerCase() ? a[field].toLowerCase() < b[field].toLowerCase() ? -1 : 1 : 0);
  }

}
1
Andre Coetzee

Pour Angular 5+ Version, nous pouvons utiliser Le paquet ngx-order-pipe

Lien du tutoriel source

Installer le paquet

$ npm install ngx-order-pipe --save

Importer dans le module apps

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { OrderModule } from 'ngx-order-pipe';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    OrderModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

utiliser n'importe où

  <ul>
    <li *ngFor="let item of (dummyData | orderBy:'name') ">
      {{item.name}}
    </li>
  </ul>
0
Code Spy

orderby Pipe in angulaire JS prendra en charge mais angulaire (versions supérieures) ne supportera pas . S'il vous plaît trouver les détails discutés pour augmenter la vitesse d'exécution de son obsolète.

https://angular.io/guide/pipes#appendix-no-filterpipe-or- orderbypipe

0
Mark Macneil Bikeio

Dans la version actuelle de Angular2, les canaux orderBy et ArraySort ne sont pas pris en charge. Pour cela, vous devez écrire/utiliser des canaux personnalisés.

0
Siva