Skip to content

Commit

Permalink
Add {{reject-by}} helper
Browse files Browse the repository at this point in the history
  • Loading branch information
XiphiasUvella committed Feb 26, 2016
1 parent 0f0e942 commit 577db36
Show file tree
Hide file tree
Showing 5 changed files with 189 additions and 0 deletions.
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ For action helpers, this will mean better currying semantics:
+ [`map-by`](#map-by)
+ [`sort-by`](#sort-by)
+ [`filter-by`](#filter-by)
+ [`reject-by`](#reject-by)
+ [`find-by`](#find-by)
+ [`intersect`](#intersect)
+ [`union`](#union)
Expand Down Expand Up @@ -241,6 +242,33 @@ You can also pass an action as third argument:
**[⬆️ back to top](#available-helpers)**
#### `reject-by`
The inverse of filter by.
```hbs
{{#each (reject-by "isActive" true users) as |user|}}
{{user.name}} is not active!
{{/each}}
```
If you omit the third argument it will test if the property is falsey.
```hbs
{{#each (reject-by "address" users) as |user|}}
{{user.name}} does not have an address specified!
{{/each}}
```
You can also pass an action as third argument:
```hbs
{{#each (reject-by "age" (action "youngerThan" 18) users) as |user|}}
{{user.name}} is older than eighteen!
{{/each}}
```
**[⬆️ back to top](#available-helpers)**
#### `find-by`
Returns the first entry matching the given value.
Expand Down
58 changes: 58 additions & 0 deletions addon/helpers/reject-by.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import Ember from 'ember';

const {
Helper,
computed: { filter, filterBy },
defineProperty,
get,
isArray,
isEmpty,
observer,
set
} = Ember;

export default Helper.extend({
compute([byPath, value, array]) {

if (!isArray(array) && isArray(value)) {
array = value;
value = undefined;
}

set(this, 'array', array);
set(this, 'byPath', byPath);
set(this, 'value', value);

return get(this, 'content');
},

byPathDidChange: observer('byPath', 'value', function() {
let byPath = get(this, 'byPath');
let value = get(this, 'value');

if (isEmpty(byPath)) {
defineProperty(this, 'content', []);
return;
}

let filterFn;

if (value) {
if (typeof value === 'function') {
filterFn = (item) => !value(get(item, byPath));
} else {
filterFn = (item) => get(item, byPath) !== value;
}
} else {
filterFn = (item) => isEmpty(get(item, byPath));
}

let cp = filter(`array.@each.${byPath}`, filterFn);

defineProperty(this, 'content', cp);
}),

contentDidChange: observer('content', function() {
this.recompute();
})
});
1 change: 1 addition & 0 deletions addon/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export { default as JoinHelper } from './helpers/join';
export { default as MapByHelper } from './helpers/map-by';
export { default as PipeHelper } from './helpers/pipe';
export { default as RangeHelper } from './helpers/range';
export { default as RejectByHelper } from './helpers/reject-by';
export { default as RepeatHelper } from './helpers/repeat';
export { default as SortByHelper } from './helpers/sort-by';
export { default as TakeHelper } from './helpers/take';
Expand Down
1 change: 1 addition & 0 deletions app/helpers/reject-by.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default, rejectBy } from 'ember-composable-helpers/helpers/reject-by';
101 changes: 101 additions & 0 deletions tests/integration/helpers/reject-by-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import Ember from 'ember';
import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';

const { A: emberArray, run, set } = Ember;

moduleForComponent('reject-by', 'Integration | Helper | {{reject-by}}', {
integration: true
});

test('It reject by value', function(assert) {
this.set('array', emberArray([
{ foo: false, name: 'a' },
{ foo: true, name: 'b' },
{ foo: false, name: 'c' }
]));

this.render(hbs`
{{~#each (reject-by 'foo' true array) as |item|~}}
{{~item.name~}}
{{~/each~}}
`);

assert.equal(this.$().text().trim(), 'ac', 'b is filtered out');
});

test('It rejects by truthiness', function(assert) {
this.set('array', emberArray([
{ foo: 'x', name: 'a' },
{ foo: undefined, name: 'b' },
{ foo: 1, name: 'c' },
{ foo: null, name: 'd' },
{ foo: [1, 2, 3], name: 'e' }
]));

this.render(hbs`
{{~#each (reject-by 'foo' array) as |item|~}}
{{~item.name~}}
{{~/each~}}
`);

assert.equal(this.$().text().trim(), 'bd', 'a, c and e are filtered out');
});

test('It recomputes the filter if array changes', function(assert) {
let array = emberArray([
{ foo: false, name: 'a' },
{ foo: true, name: 'b' },
{ foo: false, name: 'c' }
]);

this.set('array', array);

this.render(hbs`
{{~#each (reject-by 'foo' true array) as |item|~}}
{{~item.name~}}
{{~/each~}}
`);

run(() => array.pushObject({ foo: false, name: 'd' }));

assert.equal(this.$().text().trim(), 'acd', 'd is added');
});

test('It recomputes the filter if a value under given path changes', function(assert) {
let array = emberArray([
{ foo: false, name: 'a' },
{ foo: true, name: 'b' },
{ foo: false, name: 'c' }
]);

this.set('array', array);

this.render(hbs`
{{~#each (reject-by 'foo' true array) as |item|~}}
{{~item.name~}}
{{~/each~}}
`);

run(() => set(array.objectAt(1), 'foo', false));

assert.equal(this.$().text().trim(), 'abc', 'b is shown');
});

test('It can be passed an action', function(assert) {
this.set('array', emberArray([
{ foo: 1, name: 'a' },
{ foo: 2, name: 'b' },
{ foo: 3, name: 'c' }
]));

this.on('isEven', (value) => value % 2 === 0);

this.render(hbs`
{{~#each (reject-by 'foo' (action 'isEven') array) as |item|~}}
{{~item.name~}}
{{~/each~}}
`);

assert.equal(this.$().text().trim(), 'ac', 'b is filtered out');
});

0 comments on commit 577db36

Please sign in to comment.