Подтвердить что ты не робот

Заказать по выпуску трубы

Я не могу перевести этот код с Angualr 1 на Angular 2:

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

Вот что я сделал после ответа Тьерри Темплиера:

Компонент шаблона:

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

Я пытаюсь отсортировать массив Todo s, упорядоченный свойством completed. Сначала todo.completed = false а затем todo.complete = true.

Я не очень хорошо понимаю метод transform и как передать аргументы в этом методе и в методе sort.

Что такое args: string? Что такое a и b и откуда они берутся?

4b9b3361

Ответ 1

Я изменил ответ @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'"

Надеюсь, это кому-нибудь поможет.

Ответ 2

Пожалуйста, см. Https://angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipe для полного обсуждения. Эта цитата является наиболее актуальной. По сути, для крупномасштабных приложений, которые должны активно минимизироваться, логика фильтрации и сортировки должна перемещаться в сам компонент.

"Некоторые из нас могут не заботиться об агрессивном минимизации этого. Это наш выбор. Но продукт Angular не должен мешать кому-либо агрессивно минимизировать. Поэтому команда Angular решила, что все, что поставляется в Angular, будет минимизировано безопасно.

Команда Angular и многие опытные разработчики Angular настоятельно рекомендуют перенести логику фильтрации и сортировки в сам компонент. Компонент может предоставлять свойство FilterHeroes или sortedHeroes и контролировать, когда и как часто следует выполнять вспомогательную логику. Любые возможности, которые вы могли бы добавить в канал и использовать в приложении, можно записать в службу фильтрации/сортировки и внедрить в компонент ".

Ответ 3

Вы можете реализовать настраиваемый канал для этого, который использует метод 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

Ответ 4

Обновлен 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: boolean; true: убывающий порядок; false: по возрастанию;

Ответ 5

Angular не поставляется с фильтром orderBy из коробки, но если мы решим, что нам нужно, мы сможем его легко создать. Однако есть некоторые предостережения, которые нам нужно знать о скорости и минимуме. См. Ниже.

Простая труба будет выглядеть примерно так.

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

Эта трубка принимает функцию сортировки (fn) и дает ей значение по умолчанию, которое будет сортировать массив примитивов разумным способом. У нас есть возможность переопределить эту функцию сортировки, если мы хотим.

Он не принимает имя атрибута в виде строки, потому что имена атрибутов подлежат уточнению. Они изменятся, когда мы минимизируем наш код, но minifiers недостаточно умен, чтобы также минимизировать значение в строке шаблона.

Сортировочные примитивы (числа и строки)

Мы могли бы использовать это для сортировки массива чисел или строк с использованием компаратора по умолчанию:

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 быть быстрым. 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)
  }
}

Эта труба опустится в объекты, но будет медленнее. Следует использовать с осторожностью.

Ответ 6

Я создал канал 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

Ответ 7

Рекомендуем использовать lodash с помощью angular, тогда ваша труба будет следующей:

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, ...],
    ...
})

Ответ 8

Это будет работать для любого поля, которое вы передадите ему. ( ВАЖНО: Он будет указывать только в алфавитном порядке, поэтому, если вы передадите дату, он будет заказывать его как алфавит, а не как дату)

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

Ответ 9

Это хорошая замена для трубки AngularJs orderby в angular 4. Простая и простая в использовании.

Это URL-адрес github для получения дополнительной информации. 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;
  }
}

Ответ 10

Как мы знаем, фильтр и порядок удалены из 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;
          }
        });
    };
 }

Ответ 11

Вы можете использовать это для объектов:

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

}

Ответ 12

В package.json добавьте что-то вроде (эта версия подходит для Angular 2):

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

В вашем модуле машинописи (и массиве импорта):

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

Ответ 13

В текущей версии Angular2 каналы orderBy и ArraySort не поддерживаются. Для этого вам нужно написать/использовать для этого некоторые пользовательские каналы.

Ответ 14

Создана труба для сортировки. Принимает как строку, так и массив строк, сортируя по нескольким значениям.

@Pipe({name: 'orderBy'})
export class OrderBy implements PipeTransform {
    transform(array: any[], filter: any): any[] {
        if(typeof filter === 'string') {
            return this.sortAray(array, filter)
        } else {
            for (var i = filter.length -1; i >= 0; i--) {
                array = this.sortAray(array, filter[i]);
            }

            return array;
        }
    }

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

Ответ 15

pipe orderby в Angular JS будет поддерживать, но Angular (более поздние версии) не будет поддерживать. Пожалуйста, найдите детали, обсуждаемые для увеличения скорости его работы.

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

Ответ 16

Для Angular 5+ версии мы можем использовать пакет ngx-order-pipe

Ссылка на учебник

Установить пакет

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

Ответ 17

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