OrderBy ปัญหาท่อ


101

ฉันไม่สามารถแปลรหัสนี้จาก Angualr 1 เป็น Angular 2:

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

นี่คือสิ่งที่ฉันได้ทำตามคำตอบของ Thierry Templier:

แม่แบบส่วนประกอบ:

*ngFor="#todo of todos | sort"

รหัสส่วนประกอบ:

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

})

รหัสท่อ:

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

ฉันพยายามที่จะจัดเรียงอาร์เรย์ของTodos completedได้รับคำสั่งจากทรัพย์สิน ก่อนอื่นtodo.completed = falseแล้วtodo.complete = true.

ฉันไม่ค่อยเข้าใจtransformวิธีการและวิธีการส่งผ่านข้อโต้แย้งในวิธีนั้นและในsortวิธีการ

อะไรคือสิ่งที่args: stringโต้แย้ง? สิ่งที่เป็นaและbที่พวกเขามาจากไหน?


ฉันพบแพ็คเกจโมดูลนี้สำหรับ OrderBy ใน Angular5 + เวอร์ชันfreakyjolly.com/…
Code Spy

คำตอบ:


85

ฉันแก้ไขการตอบสนองของ @Thierry Templier เพื่อให้ไปป์สามารถจัดเรียงวัตถุที่กำหนดเองในเชิงมุม 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;
  }
}

และวิธีใช้:

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

หวังว่านี่จะช่วยใครบางคนได้


1
ฉันได้รับข้อความ: The pipe 'sort' could not be found. ฉันสามารถฉีดไปป์ในส่วนประกอบของฉันเช่นในท่อเชิงมุม 2 ท่อ: [ArraySortPipe] ได้หรือไม่?
Matija Župančić

ดูการตอบสนอง @Thierry TEMPLIER เกี่ยวกับวิธีการฉีดท่อเข้าไปในส่วนประกอบของแอป
Sal

คุณต้องรวม "ArraySortPipe" ในการประกาศลำดับชั้นโมดูลของคุณ บางอย่างเช่น: นำเข้า {ArraySortPipe} จาก './../../shared/filters.pipe'; ใน 'app.module.ts' และโมดูลใด ๆ ที่อยู่ข้างใต้ ใส่: ประกาศ: [ArraySortPipe]
Dudi

73

โปรดดูhttps://angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipeสำหรับการสนทนาแบบเต็ม คำพูดนี้ตรงประเด็นที่สุด โดยพื้นฐานแล้วสำหรับแอปขนาดใหญ่ที่ควรลดขนาดอย่างจริงจังตรรกะการกรองและการเรียงลำดับควรย้ายไปที่ส่วนประกอบนั้นเอง

"พวกเราบางคนอาจไม่สนใจที่จะลดขนาดนี้ลงอย่างจริงจังนั่นเป็นทางเลือกของเรา แต่ผลิตภัณฑ์ Angular ไม่ควรป้องกันไม่ให้ผู้อื่นทำการย่อขนาดอย่างก้าวร้าวดังนั้นทีม Angular จึงตัดสินใจว่าทุกอย่างที่จัดส่งใน Angular จะลดน้อยลงอย่างปลอดภัย

ทีม Angular และนักพัฒนา Angular ที่มีประสบการณ์หลายคนขอแนะนำอย่างยิ่งให้คุณย้ายการกรองและการเรียงลำดับตรรกะไปไว้ในส่วนประกอบนั้นเอง คอมโพเนนต์สามารถแสดงคุณสมบัติ filteredHeroes หรือ sortedHeroes และควบคุมเวลาและความถี่ในการเรียกใช้ตรรกะสนับสนุน ความสามารถใด ๆ ที่คุณจะใส่ไว้ในไพพ์และแชร์ข้ามแอพสามารถเขียนลงในบริการกรอง / คัดแยกและแทรกเข้าไปในคอมโพเนนต์ "


7
คุณควรย้ายตรรกะ "เข้าสู่ส่วนประกอบเอง" ในลักษณะที่สามารถ "ควบคุมเวลาและความถี่ในการดำเนินการตรรกะที่สนับสนุน" ได้อย่างไร มีตัวอย่างที่ดีในการปฏิบัติตามนี้หรือไม่?
Mzzzzzz

1
@Mzzzzzz ที่กล่าวถึงคุณสมบัติเช่นfilteredHeroesและsortedHeroesฉันคิดว่าแนวคิดก็คือในขณะที่เริ่มต้นส่วนประกอบคุณจะเรียกใช้ตรรกะการเรียงลำดับ / กรองบางอย่าง (อาจเรียกวิธีการจาก ngOnInit) จากนั้นตั้งค่าคุณสมบัตินั้นด้วยผลลัพธ์ที่เรียงลำดับ / กรองและ เรียกใช้ตรรกะ / อัปเดตคุณสมบัติอีกครั้งหากมีบางสิ่งที่ทำให้เกิดความต้องการ (เช่นการโต้ตอบของผู้ใช้เรียก AJAX เพื่อรับฮีโร่เพิ่มหรือผู้ใช้คลิกช่องทำเครื่องหมายเพื่อกรองครึ่งหนึ่งออกไปตามเกณฑ์บางอย่างเป็นต้น)
jmq

ฉันควรใช้มันในส่วนประกอบหรือใช้วิธีแก้ปัญหาข้างต้น (ท่อที่กำหนดเอง)?
Ron Rofe

FYI: เป้าหมายลิงก์นั้นหายไป
tommueller

42

คุณสามารถใช้ไปป์ที่กำหนดเองเพื่อใช้ประโยชน์จากsortเมธอดของอาร์เรย์:

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

แล้วใช้ท่อนี้ตามที่อธิบายไว้ด้านล่าง อย่าลืมระบุไปป์ของคุณในpipesแอตทริบิวต์ของส่วนประกอบ:

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

เป็นตัวอย่างง่ายๆสำหรับอาร์เรย์ที่มีค่าสตริง แต่คุณสามารถมีการประมวลผลการเรียงลำดับขั้นสูงได้ (ขึ้นอยู่กับคุณสมบัติของอ็อบเจ็กต์ในกรณีของอาร์เรย์อ็อบเจ็กต์ตามพารามิเตอร์การเรียงลำดับ ... )

นี่คือ plunkr สำหรับการนี้: https://plnkr.co/edit/WbzqDDOqN1oAhvqMkQRQ?p=preview

หวังว่ามันจะช่วยคุณ Thierry


1
ขอบคุณสำหรับคำตอบคุณสามารถอธิบายวิธีการจัดเรียงได้หรือไม่?

1
ในความเป็นจริงsortวิธีนี้เป็นวิธีการของArrayวัตถุJavaScript ดูลิงค์นี้developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… .
Thierry Templier

ตกลงฉันเข้าใจแล้วมันใช้วิธีการเรียงลำดับจาวาสคริปต์พร้อมฟังก์ชันเปรียบเทียบเป็นอาร์กิวเมนต์ ขอบคุณ!

1
น่าเสียดายที่ Plunker เลิกใช้งานแล้ว เทียรี่?

4
การpipes: [..]ประกาศใช้ไม่ได้อีกต่อไป (และไม่จำเป็นอีกต่อไป)
phil294

9

อัปเดต OrderByPipe: แก้ไขไม่เรียงลำดับสตริง

สร้างคลาส 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;
  }
}

ในตัวควบคุมของคุณ:

@Component({
pipes: [OrderByPipe]
})

หรือในไฟล์

 declarations: [OrderByPipe]

ใน html ของคุณ:

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

ObjFieldName: ชื่อฟิลด์อ็อบเจ็กต์ที่คุณต้องการจัดเรียง

OrderByType: บูลีน; จริง: จากมากไปหาน้อย; เท็จ: จากน้อยไปมาก;


สำหรับอาร์กิวเมนต์สตริงที่เปรียบเทียบ [orderField] - b [orderField] ส่งคืน NaN
Piotr Pęczek

สำหรับอาร์กิวเมนต์วันที่จะไม่ทำงาน รูปแบบวันที่เป็นข้อความจะเรียงลำดับไม่ถูกต้อง
Rafael Pizao

9

Angular ไม่ได้มาพร้อมกับคำสั่งโดยกรองนอกกรอบ แต่ถ้าเราตัดสินใจว่าเราต้องการเราสามารถสร้างได้อย่างง่ายดาย อย่างไรก็ตามมีข้อแม้บางประการที่เราต้องระวังเกี่ยวกับความเร็วและการลดขนาด ดูด้านล่าง

ท่อธรรมดาจะมีลักษณะเช่นนี้

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)
  }
}

ไปป์นี้ยอมรับฟังก์ชั่น sort ( fn) และให้เป็นค่าเริ่มต้นที่จะจัดเรียงอาร์เรย์ของ primitives ด้วยวิธีที่สมเหตุสมผล เรามีตัวเลือกในการแทนที่ฟังก์ชันการเรียงลำดับนี้หากต้องการ

ไม่ยอมรับชื่อแอตทริบิวต์เป็นสตริงเนื่องจากชื่อแอตทริบิวต์อาจมีการลดขนาด ค่าเหล่านี้จะเปลี่ยนไปเมื่อเราย่อขนาดโค้ดของเรา แต่ตัวย่อไม่ฉลาดพอที่จะย่อค่าในสตริงเทมเพลต

การเรียงลำดับดั้งเดิม (ตัวเลขและสตริง)

เราสามารถใช้สิ่งนี้เพื่อจัดเรียงอาร์เรย์ของตัวเลขหรือสตริงโดยใช้ตัวเปรียบเทียบเริ่มต้น:

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']
}

การจัดเรียงอาร์เรย์ของวัตถุ

หากเราต้องการจัดเรียงอาร์เรย์ของวัตถุเราสามารถให้ฟังก์ชันเปรียบเทียบได้

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

ข้อควรระวัง - ท่อบริสุทธิ์และไม่บริสุทธิ์

Angular 2 มีแนวคิดเกี่ยวกับท่อที่บริสุทธิ์และไม่บริสุทธิ์

ท่อบริสุทธิ์ช่วยเพิ่มประสิทธิภาพการตรวจจับการเปลี่ยนแปลงโดยใช้เอกลักษณ์ของวัตถุ ซึ่งหมายความว่าไปป์จะทำงานก็ต่อเมื่อออบเจ็กต์อินพุตเปลี่ยนเอกลักษณ์เช่นหากเราเพิ่มรายการใหม่ในอาร์เรย์ มันจะไม่ลงมาในวัตถุ ซึ่งหมายความว่าหากเราเปลี่ยนแอตทริบิวต์ที่ซ้อนกันthis.cats[2].name = "Fluffy"ตัวอย่างเช่นไปป์จะไม่ทำงานซ้ำ สิ่งนี้ช่วยให้ Angular เป็นไปอย่างรวดเร็ว ท่อเชิงมุมจะบริสุทธิ์โดยปริยาย

ในทางกลับกันท่อที่ไม่บริสุทธิ์จะตรวจสอบคุณสมบัติของวัตถุ ซึ่งอาจทำให้ช้าลงมาก เนื่องจากไม่สามารถรับประกันได้ว่าฟังก์ชันไพพ์จะทำอะไร (อาจเรียงลำดับแตกต่างกันไปตามช่วงเวลาของวันเป็นต้น) ไปป์ที่ไม่บริสุทธิ์จะทำงานทุกครั้งที่เกิดเหตุการณ์แบบอะซิงโครนัส สิ่งนี้จะทำให้แอปของคุณช้าลงอย่างมากหากอาร์เรย์มีขนาดใหญ่

ท่อข้างบนล้วนๆ ซึ่งหมายความว่ามันจะทำงานก็ต่อเมื่อวัตถุในอาร์เรย์ไม่เปลี่ยนรูป หากคุณเปลี่ยนแมวคุณต้องแทนที่วัตถุ cat ทั้งหมดด้วยวัตถุใหม่

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

เราสามารถเปลี่ยนข้างต้นเป็นท่อที่ไม่บริสุทธิ์โดยตั้งค่าแอตทริบิวต์บริสุทธิ์:

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)
  }
}

ท่อนี้จะไหลลงสู่วัตถุ แต่จะช้ากว่า ใช้ด้วยความระมัดระวัง


ขอบคุณ .. ช่วยได้มาก แต่คำถามหนึ่ง .. ถ้าเราไม่ควรใช้ท่อหรือตัวกรองในการคัดแยกแนวทางที่ดีที่สุดคืออะไร? ฉันค้นหาทุกที่ทุกคนแก้ปัญหาด้วยการสร้างท่อ
Pavankumar Shukla

@PavanShukla คุณสามารถใช้ไพพ์เพียงตรวจสอบให้แน่ใจว่ารายการอาร์เรย์ของคุณไม่เปลี่ยนรูปและสร้างไปป์ที่บริสุทธิ์ หรือถ้าคุณไม่มีอาร์เรย์ขนาดใหญ่ให้สร้างท่อที่ไม่บริสุทธิ์แล้วเรียงลำดับการแสดงผลแต่ละครั้ง อีกวิธีหนึ่งคือสร้างอาร์เรย์ที่เรียงลำดับเป็นแอตทริบิวต์ของส่วนประกอบของคุณและแสดงผลนั้น
superluminary

ฉันใช้ array.sort logic ในการคลิกของแต่ละหัวข้อ cloumn ฉันกำลังดำเนินการนี้กับอาร์เรย์ข้อมูลการแสดงผล .. เป็นวิธีที่ดีหรือไม่?
Pavankumar Shukla

7

ฉันได้สร้างไปป์ OrderBy ที่ทำในสิ่งที่คุณต้องการ สนับสนุนความสามารถในการจัดเรียงในหลายคอลัมน์ของวัตถุที่นับได้เช่นกัน

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

ไปป์นี้อนุญาตให้เพิ่มรายการเพิ่มเติมในอาร์เรย์หลังจากแสดงผลเพจและจะเรียงลำดับอาร์เรย์ด้วยการอัปเดตแบบไดนามิก

ฉันมีการเขียนขึ้นเกี่ยวกับกระบวนการที่นี่

และนี่คือตัวอย่างการใช้งาน: http://fuelinteractive.github.io/fuel-ui/#/pipe/orderbyและhttps://plnkr.co/edit/DHLVc0?p=info


คุณไม่ได้จัดการค่าว่าง
Ali Habibzadeh

ถ้า (a == null) a = 0; ถ้า (b == null) b = 0;
Ali Habibzadeh

นอกจากนี้ค่าที่มีมูลค่าเท่ากันก็น่ากลัวและเคลื่อนไหวเมื่อคุณคลิกไปรอบ ๆ ในอินเทอร์เฟซ
Ali Habibzadeh

@XGreen ขอบคุณสำหรับสิ่งนี้ ฉันจะเพิ่มการรองรับสำหรับค่า null / ไม่ได้กำหนดในการอัปเดต fuel-ui ครั้งต่อไป สำหรับความโดดเด่นของค่าที่เท่ากันฉันไม่เห็นสิ่งนี้ สิ่งที่เบราว์เซอร์ที่คุณใช้?
Cory Shaw

Chrome เวอร์ชัน 50.0.2661.86 (64 บิต), OSX El Capitan
Ali Habibzadeh

4

แนะนำให้คุณใช้ lodash กับเชิงมุมจากนั้นท่อของคุณจะอยู่ถัดไป:

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]);
    }

}

และใช้ใน html เช่น

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

และอย่าลืมเพิ่ม Pipe ในโมดูลของคุณ

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

ฉันชอบแนวทางของคุณАлександрПетрик แต่ฉันชอบส่งอาร์เรย์ใน template: orderBy: ['field1', 'field2'] จากนั้นเรียกไปป์: return _.sortBy (array, args);
Eric

1
ปัญหาในการใช้ _.sortBy คือคุณไม่สามารถระบุลำดับที่สืบเนื่องมาได้ ฉันพบว่าการใช้ _.orderBy คุณสามารถระบุลำดับที่กำหนดเองสำหรับทุกฟิลด์ เช่น: _.orderBy (array, ['field1', 'field2'], ['asc', 'desc'])
Eric

3

สิ่งนี้จะใช้ได้กับทุกสาขาที่คุณผ่านไป ( สำคัญ:จะเรียงลำดับตามตัวอักษรเท่านั้นดังนั้นหากคุณผ่านวันที่มันจะเรียงลำดับเป็นตัวอักษรไม่ใช่วันที่)

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

โพสต์ตัวอย่างการใช้งานได้ไหม
TheUnreal

ฉันไม่สามารถรวบรวมรหัสที่คุณให้มา ฉันได้รับข้อผิดพลาดแจ้งว่า@Componentไม่มีpipesคุณสมบัติ
Azimuth

3

นี่คือการเปลี่ยนที่ดีสำหรับ AngularJs orderbyท่อเหลี่ยม 4 ใช้งานง่ายและสะดวก

นี่คือ github URL สำหรับข้อมูลเพิ่มเติม 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;
  }
}

2

อย่างที่เราทราบกันดีว่าตัวกรองและลำดับโดยถูกลบออกจาก ANGULAR 2 และเราจำเป็นต้องเขียนของเราเองนี่คือตัวอย่างที่ดีเกี่ยวกับPlunkerและบทความโดยละเอียด

มันใช้ทั้งตัวกรองและ orderby นี่คือรหัสสำหรับท่อสั่งซื้อ

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

คุณสามารถใช้สิ่งนี้สำหรับวัตถุ:

@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);
  }

}

2

ใน package.json ให้เพิ่มสิ่งที่ต้องการ (เวอร์ชันนี้ใช้ได้สำหรับ Angular 2):

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

ในโมดูล typescript ของคุณ (และนำเข้าอาร์เรย์):

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

0

ในเวอร์ชันปัจจุบันของ Angular2 ไม่รองรับไปป์ orderBy และ ArraySort คุณต้องเขียน / ใช้ไปป์ที่กำหนดเองสำหรับสิ่งนี้


0

สำหรับ Angular 5+ Versionเราสามารถใช้ngx-order-pipe package

ลิงค์สอนที่มา

ติดตั้งแพ็คเกจ

$ npm install ngx-order-pipe --save

นำเข้าในโมดูลแอพ

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 { }

ใช้ได้ทุกที่

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

0

orderby ท่อในเชิงมุม JSจะสนับสนุน แต่เชิงมุม (รุ่นที่สูงกว่า) จะไม่สนับสนุน โปรดดูรายละเอียดที่เขากล่าวถึงเพื่อเพิ่มความเร็วในการทำงานที่ล้าสมัย

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


0
<!-- const cars=['Audi','Merc','BMW','Volvo','Tesla'] -->

<ul>
  <li *ngFor="let car of cars">{{car}}</li>
</ul>


/*
 *ngFor="let c of oneDimArray | sortBy:'asc'"
 *ngFor="let c of arrayOfObjects | sortBy:'asc':'propertyName'"
*/
import { Pipe, PipeTransform } from '@angular/core';
import { orderBy } from 'lodash';

@Pipe({ name: 'sortBy' })
export class SortByPipe implements PipeTransform {

  transform(value: any[], order = '', column: string = ''): any[] {
    if (!value || order === '' || !order) { return value; } // no array
    if (!column || column === '') { return sortBy(value); } // sort 1d array
    if (value.length <= 1) { return value; } // array with only one item
    return orderBy(value, [column], [order]);
  }
}

-1
Component template:
todos| sort: ‘property’:’asc|desc’

Pipe code:

import { Pipe,PipeTransform  } from "angular/core";
import {Todo} from './todo';

@Pipe({
  name: "sort"
})
export class TodosSortPipe implements PipeTransform {
  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 {`enter code here`
        return 0;
      }
    });
    return array;
  }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.