Skip to content

Commit

Permalink
feat(danrevah#20): Add orderBy pipe
Browse files Browse the repository at this point in the history
  • Loading branch information
danrevah committed Jan 28, 2017
1 parent 784f169 commit 71a4e39
Show file tree
Hide file tree
Showing 4 changed files with 238 additions and 2 deletions.
49 changes: 48 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
- [sample](#sample)
- [groupBy](#groupby)
- [filterBy](#filterby)
- [orderBy](#orderBy)
- [Object](#object)
- [keys](#keys)
- [values](#values)
Expand Down Expand Up @@ -611,7 +612,7 @@ this.arrayNestedObject = [

### filterBy

Returns object of grouped by items by discriminator
Returns object array of grouped by items by discriminator

**Usage:** `array | filterBy: [prop, nested.prop, ...]: search: [strict | optional]`

Expand All @@ -638,6 +639,52 @@ this.users = [
<!-- Output: "[{id: 1, first_name: 'John', last_name: 'Doe', work: { company: 'Foo Tech', previous_company: '' }}]" -->
```

### orderBy

Returns ordered array by configuration

**Usage:** `array | orderBy: [prop, nested.prop, array of props, ...]`

```typescript
const numbers = [2, 1, 3];

const obj = [
{id: 4, name: 'Dave', amount: 2},
{id: 2, name: 'Michael', amount: 2},
{id: 3, name: 'Dan', amount: 1},
{id: 1, name: 'John', amount: 1}
];

const deepObj = [
{id: 1, name: 'John', amount: 1337, deep: {prop: 4}},
{id: 2, name: 'Michael', amount: 42, deep: {prop: 2}},
{id: 3, name: 'Dan', amount: 1, deep: {prop: 1}},
{id: 4, name: 'Dave', amount: 2, deep: {prop: 3}}
];
```

```html
<!-- Returns array orderd by value -->
<p>{{ numbers | orderBy }}</p> <!--- Output: [1, 2, 3] --->
<p>{{ numbers | orderBy: '-' }}</p> <!--- Output: [3, 2, 1] --->

<!-- Returns array orderd by value of property -->
<p>{{ deepObj | orderBy: 'amount' }}</p>
<!--- Output: [{id: 3, ...}, {id: 4, ...}, {id: 2, ...}, {id: 1, ...}] --->
<p>{{ deepObj | orderBy: '-amount' }}</p>
<!--- Output: [{id: 1, ...}, {id: 2, ...}, {id: 4, ...}, {id: 3, ...}] --->

<!-- Returns array orderd by value of deep property -->
<p>{{ deepObj | orderBy: 'deep.prop' }}</p>
<!--- Output: [{id: 3, ...}, {id: 2, ...}, {id: 4, ...}, {id: 1, ...}] --->
<p>{{ deepObj | orderBy: '-deep.prop' }}</p>
<!--- Output: [{id: 1, ...}, {id: 4, ...}, {id: 2, ...}, {id: 3, ...}] --->

<!-- Returns array orderd by mutliple properties -->
<p>{{ obj | orderBy: ['amount', 'id'] }}</p>
<!--- Output: [{id: 1, ...}, {id: 3, ...}, {id: 2, ...}, {id: 4, ...}] --->
```

## Object

### keys
Expand Down
128 changes: 128 additions & 0 deletions src/app/pipes/array/order-by.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import {OrderByPipe} from './order-by';

describe('OrderByPipe', () => {
const testArray = [
{id: 1, name: 'John', amount: 1337},
{id: 2, name: 'Michael', amount: 42},
{id: 3, name: 'Dan', amount: 1},
{id: 4, name: 'Dave', amount: 2}
];

let pipe: OrderByPipe;

beforeEach(() => {
pipe = new OrderByPipe();
});

it('should not do anything in-case of not an array', () => {
expect(pipe.transform('foo')).toEqual('foo');
expect(pipe.transform(null)).toEqual(null);
expect(pipe.transform(undefined)).toEqual(undefined);
expect(pipe.transform(42)).toEqual(42);
expect(pipe.transform({foo: 1, bar: 2})).toEqual({foo: 1, bar: 2});
});

it('should create a new version of the array', () => {
const arr = [3, 2, 1];
expect(pipe.transform(arr)).toEqual([1, 2, 3]);
expect(arr).toEqual([3, 2, 1]);
});

it('should order by value if there is no config', () => {
expect(pipe.transform([3, 2, 1])).toEqual([1, 2, 3]);
expect(pipe.transform(['c', 'b', 'a'])).toEqual(['a', 'b', 'c']);
});

it('should order by reverse value if there a stringy value of `-`', () => {
expect(pipe.transform([3, 2, 1], '-')).toEqual([3, 2, 1]);
expect(pipe.transform(['c', 'b', 'a'], '-')).toEqual(['c', 'b', 'a']);
expect(pipe.transform([1, 2, 3], '-')).toEqual([3, 2, 1]);
expect(pipe.transform(['a', 'b', 'c'], '-')).toEqual(['c', 'b', 'a']);
});

it('should order by value if there a stringy value of `+`', () => {
expect(pipe.transform([3, 2, 1], '+')).toEqual([1, 2, 3]);
expect(pipe.transform(['c', 'b', 'a'], '+')).toEqual(['a', 'b', 'c']);
});

it('should order by property if there a stringy value of `+property` or `property`', () => {
expect(pipe.transform(testArray, 'amount')).toEqual([
{id: 3, name: 'Dan', amount: 1},
{id: 4, name: 'Dave', amount: 2},
{id: 2, name: 'Michael', amount: 42},
{id: 1, name: 'John', amount: 1337}
]);

expect(pipe.transform(testArray, '+amount')).toEqual([
{id: 3, name: 'Dan', amount: 1},
{id: 4, name: 'Dave', amount: 2},
{id: 2, name: 'Michael', amount: 42},
{id: 1, name: 'John', amount: 1337}
]);
});

it('should reverse order by property if there a stringy value of `-property`', () => {
expect(pipe.transform(testArray, '-amount')).toEqual([
{id: 1, name: 'John', amount: 1337},
{id: 2, name: 'Michael', amount: 42},
{id: 4, name: 'Dave', amount: 2},
{id: 3, name: 'Dan', amount: 1}
]);
});

it('should reverse order by multiple properties if there an array values', () => {
expect(pipe.transform([
{id: 4, name: 'Dave', amount: 2},
{id: 2, name: 'Michael', amount: 2},
{id: 3, name: 'Dan', amount: 1},
{id: 1, name: 'John', amount: 1}
], ['amount', '+id'])).toEqual([
{id: 1, name: 'John', amount: 1},
{id: 3, name: 'Dan', amount: 1},
{id: 2, name: 'Michael', amount: 2},
{id: 4, name: 'Dave', amount: 2}
]);
});

it('should reverse order by multiple properties if there an array values', () => {
expect(pipe.transform([
{id: 2, name: 'b', amount: 2},
{id: 2, name: 'a', amount: 2},
{id: 1, name: 'd', amount: 1},
{id: 1, name: 'c', amount: 1}
], ['amount', '+id', '-name'])).toEqual([
{id: 1, name: 'd', amount: 1},
{id: 1, name: 'c', amount: 1},
{id: 2, name: 'b', amount: 2},
{id: 2, name: 'a', amount: 2}
]);
});

it('should order by deep property', () => {
expect(pipe.transform([
{id: 1, name: 'John', amount: 1337, deep: {prop: 4}},
{id: 2, name: 'Michael', amount: 42, deep: {prop: 2}},
{id: 3, name: 'Dan', amount: 1, deep: {prop: 1}},
{id: 4, name: 'Dave', amount: 2, deep: {prop: 3}}
], ['deep.prop'])).toEqual([
{id: 3, name: 'Dan', amount: 1, deep: {prop: 1}},
{id: 2, name: 'Michael', amount: 42, deep: {prop: 2}},
{id: 4, name: 'Dave', amount: 2, deep: {prop: 3}},
{id: 1, name: 'John', amount: 1337, deep: {prop: 4}}
]);
});

it('should order by deep property', () => {
expect(pipe.transform([
{id: 1, name: 'John', amount: 1337, deep: {prop: 4}},
{id: 2, name: 'Michael', amount: 42, deep: {prop: 2}},
{id: 3, name: 'Dan', amount: 1, deep: {prop: 1}},
{id: 4, name: 'Dave', amount: 2, deep: {prop: 3}}
], ['-deep.prop'])).toEqual([
{id: 1, name: 'John', amount: 1337, deep: {prop: 4}},
{id: 4, name: 'Dave', amount: 2, deep: {prop: 3}},
{id: 2, name: 'Michael', amount: 42, deep: {prop: 2}},
{id: 3, name: 'Dan', amount: 1, deep: {prop: 1}}
]);
});
});
59 changes: 59 additions & 0 deletions src/app/pipes/array/order-by.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import {PipeTransform, Pipe} from '@angular/core';
import GeneralHelper from '../helpers/helpers';

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

transform(arr: any, config?: any): any[] {
if (!Array.isArray(arr)) {
return arr;
}

const out = [...arr];

if (Array.isArray(config)) {

return out.sort((a, b) => {
let pos;

for (let i=0, l=config.length; i<l; ++i) {
const sign = config[i].substr(0, 1);
const prop = config[i].replace(/^[-+]/, '');
const asc = sign !== '-';

pos = OrderByPipe.orderCompare(prop, asc, a, b);
if (pos !== 0) break;
}

return pos;
});
} else if (GeneralHelper.isString(config)) {
const sign = config.substr(0, 1);
const prop = config.replace(/^[-+]/, '');
const asc = sign !== '-';

if (config.length === 1) {
return asc ? out.sort() : out.sort().reverse();
}
return out.sort(OrderByPipe.orderCompare.bind(this, prop, asc));
}

return out.sort();
}

static orderCompare(prop, asc, a, b) {
if (GeneralHelper.isString(a) && GeneralHelper.isString(b)) {
return a.toLowerCase().localeCompare(b.toLowerCase());
}

const fir = GeneralHelper.extractDeepPropertyByMapKey(a, prop);
const sec = GeneralHelper.extractDeepPropertyByMapKey(b, prop);

if (fir === sec) {
return 0;
}

const pos = fir < sec ? -1 : 1;
return asc ? pos : -pos;
}
}
4 changes: 3 additions & 1 deletion src/app/pipes/string/underscore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ export class UnderscorePipe implements PipeTransform {

transform(text: any, chars: string = '\\s'): string {
return GeneralHelper.isString(text)
? text.replace(/[A-Z]/g, (c, k) => k ? `_${c.toLowerCase()}` : c.toLowerCase())
? text.trim()
.replace(/\s+/g, '')
.replace(/[A-Z]/g, (c, k) => k ? `_${c.toLowerCase()}` : c.toLowerCase())
: text;
}
}

0 comments on commit 71a4e39

Please sign in to comment.