Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add a TakePipe feature for arrays #247

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
- [orderByImpure](#orderbyimpure)
- [chunk](#chunk)
- [fromPairs](#fromPairs)
- [take](#take)
- [Object](#object)
- [keys](#keys)
- [values](#values)
Expand Down Expand Up @@ -849,6 +850,23 @@ Returns object of an array of key value pairs
<p>{{ [['foo', [1, 2]], ['bar', [3, 4]]] | fromPairs }}</p> <!-- Output: "{foo: [1, 2], bar: [3, 4]}" -->
```

### take
Returns a slice of an array or of a string with n number of elements specified using `count`,
either from the beginning or from the end.

**Usage:** `array | take: [from:'start'|'end'|default='start']:[count:number|default = 1]`

```html
<p>{{ [1, 2, 3, 4, 5] | take }}</p> <!-- Array: [1] -->
<p>{{ [1, 2, 3, 4, 5] | take:'end':2 }}</p> <!-- Array: [4, 5] -->
<p>{{ "Angular is awesome" | take:'start':7 }}</p> <!-- Output: "Angular" -->
```

```typescript
this.topTwoFrameworks = this.takePipe.transform(['React', 'Angular', 'Next', 'Vue', 'Svelte'], 'start', 2);
console.log(this.topTwoFrameworks) // Returns: ['React', 'Angular']
```

## Object

### keys
Expand Down
5 changes: 4 additions & 1 deletion src/ng-pipes/pipes/array/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { OrderByImpurePipe } from './order-by-impure';
import { RangePipe } from './range';
import { ChunkPipe } from './chunk';
import { FromPairsPipe } from './from-pairs';
import { TakePipe } from './take';

const ARRAY_PIPES = [
DiffPipe,
Expand All @@ -48,7 +49,8 @@ const ARRAY_PIPES = [
OrderByImpurePipe,
RangePipe,
ChunkPipe,
FromPairsPipe
FromPairsPipe,
TakePipe,
];

@NgModule({
Expand Down Expand Up @@ -82,3 +84,4 @@ export { OrderByImpurePipe } from './order-by-impure';
export { RangePipe } from './range';
export { ChunkPipe } from './chunk';
export { FromPairsPipe } from './from-pairs';
export { TakePipe } from './take';
82 changes: 82 additions & 0 deletions src/ng-pipes/pipes/array/take.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { TakePipe } from './take';

describe('TakePipe', () => {
let pipe: TakePipe;

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

it('should not do anything when not an array or string', () => {
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 return a slice of array from start for a given count', () => {
const array = [1, 2, 3, 4, 5];
const result = pipe.transform(array, 'start', 3);
expect(result).toEqual([1, 2, 3]);
});

it('should return a slice of array from end for a given count', () => {
const array = [1, 2, 3, 4, 5];
const result = pipe.transform(array, 'end', 2);
expect(result).toEqual([4, 5]);
});

it('should return a slice of a string from start for a given count', () => {
const str = 'Angular is awesome!';
const result = pipe.transform(str, 'start', 7);
expect(result).toEqual('Angular');
});

it('should return a slice of a string from end for a given count', () => {
const str = 'Angular is awesome!';
const result = pipe.transform(str, 'end', 8);
expect(result).toEqual('awesome!');
});

it('should not modify original array', () => {
const target = [1, 2, 3];
pipe.transform(target);
expect(target).toEqual([1, 2, 3]);
});

it('should return the array as-is if the count is greater than the array length', () => {
const array = [1, 2, 3, 4, 5];
const result = pipe.transform(array, 'start', 10);
expect(result).toEqual([1, 2, 3, 4, 5]);
});

it('should return a slice of an array from start even for a negative value of count', () => {
const array = [1, 2, 3, 4, 5];
const result = pipe.transform(array, 'start', -2);
expect(result).toEqual([1, 2]);
});

it('should return a slice of a string from start even for a negative value of count', () => {
const str = 'Angular is awesome!';
const result = pipe.transform(str, 'start', -2);
expect(result).toEqual('An');
});

it('should return only the first element in the array with default parameters', () => {
const array = ['Angular', 'is', 'awesome', '!'];
const result = pipe.transform(array);
expect(result).toEqual(['Angular']);
});

it('should return an empty array for a count of 0 and a `from` value of tart', () => {
const array = [1, 2, 3, 4, 5];
const result = pipe.transform(array, 'start', 0);
expect(result).toEqual([]);
});

it('should return an empty array for a count of 0 and a `from` value of end', () => {
const array = [1, 2, 3, 4, 5];
const result = pipe.transform(array, 'end', 0);
expect(result).toEqual([]);
});
});
28 changes: 28 additions & 0 deletions src/ng-pipes/pipes/array/take.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Pipe, PipeTransform } from '@angular/core';
import { isString } from '../helpers/helpers';

@Pipe({ name: 'take' })
export class TakePipe implements PipeTransform {
transform(input: any, from: 'start' | 'end' = 'start', count: number = 1): any {
const isInputString = isString(input);
if (isInputString) {
input = input.split('');
}

let transformedArray = [];
const isArray = Array.isArray(input);

if (isArray) {
count = Math.min(input.length, Math.abs(count));
if (count === 0) {
transformedArray = [];
} else {
transformedArray = from === 'start' ? input.slice(0, Math.abs(count)) : input.slice(count * -1);
}
} else {
transformedArray = input;
}

return isInputString ? transformedArray.join('') : transformedArray;
}
}