Skip to content

Instantly share code, notes, and snippets.

@runspired
Last active May 23, 2019 18:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save runspired/2b21509015ed63ffce12b37bebc5acba to your computer and use it in GitHub Desktop.
Save runspired/2b21509015ed63ffce12b37bebc5acba to your computer and use it in GitHub Desktop.
Buffered Filter
import Ember from 'ember';
export default Ember.Component.extend({
});
import Ember from 'ember';
import randomName from '../generate-name';
const { computed, get } = Ember;
let _id = 0;
let filteredSuffix = '-filtered';
let unfilteredSuffix = '-unfiltered';
export default Ember.Controller.extend({
appName: 'Ember Twiddle',
// for tracking whether we recomputed
filterComputations: 0,
filterUpdates: 0,
sortComputations: 0,
_filteredData: null,
_filteredMemebership: null,
filteredData: computed('data.@each.name', function() {
this.incrementProperty('filterComputations');
let newMembership = Object.create(null);
let newMemberCount = 0;
let existingMembership = this._filteredMemebership;
let membershipHasChanged = false;
let existingMemberCount = existingMembership ? Object.keys(existingMembership).length : 0;
let filtered = get(this, 'data')
.filter(item => {
let name = get(item, 'name');
if (name && name.indexOf(filteredSuffix) !== -1) {
newMemberCount++;
newMembership[name] = true;
if (existingMembership && existingMembership[name] !== true) {
// we encountered a new member
membershipHasChanged = true;
}
return true;
}
return false;
});
if (newMemberCount !== existingMemberCount) {
// a removal has occurred
membershipHasChanged = true;
}
if (!membershipHasChanged) {
return this._filteredData;
}
this.incrementProperty('filterUpdates');
this._filteredData = filtered;
this._filteredMemebership = newMembership;
return filtered;
}),
sortedData: computed('filterUpdates', function() {
this.incrementProperty('sortComputations');
return this.get('filteredData')
.toArray() // don't sort the original reference
.sort((a, b) => {
return get(a, 'name') < get(b, 'name') ? -1 : 1;
});
}),
init() {
this._super(...arguments);
// seed some initial users
this.store.push({ data: [
{ type: 'user', id: `${_id}`, attributes: { name: randomName(_id++, filteredSuffix) } },
{ type: 'user', id: `${_id}`, attributes: { name: randomName(_id++, filteredSuffix) } },
{ type: 'user', id: `${_id}`, attributes: { name: randomName(_id++, filteredSuffix) } },
{ type: 'user', id: `${_id}`, attributes: { name: randomName(_id++, unfilteredSuffix) } },
{ type: 'user', id: `${_id}`, attributes: { name: randomName(_id++, unfilteredSuffix) } },
{ type: 'user', id: `${_id}`, attributes: { name: randomName(_id++, filteredSuffix) } },
] });
// all users to compute off of
this.data = this.store.peekAll('user');
},
// actions for demoing
actions: {
addFilteredUser() {
this.store.createRecord('user', { name: randomName(_id++, filteredSuffix) });
},
addUnfilteredUser() {
this.store.createRecord('user', { name: randomName(_id++, unfilteredSuffix) });
},
deleteUser(user) {
// not really a delete but good enough here
user.unloadRecord();
}
}
});
const Names = ['Chris', 'James', 'Thomas', 'William', 'Rosie', 'John', 'Michelle', 'Joanna', 'Michael', 'March']
const Alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
export default function randomName(id, suffix) {
let name = Names[id % Names.length];
let result = '';
for ( var i = 0; i < 4; i++ ) {
result += Alphabet.charAt(Math.floor(Math.random() * Alphabet.length));
}
return name + '-' + result + suffix;
}
import Ember from 'ember';
export function odd([index]) {
return index % 2 === 1;
}
export default Ember.Helper.helper(odd);
import Model from 'ember-data/model';
import attr from 'ember-data/attr';
import { belongsTo, hasMany } from 'ember-data/relationships';
export default Model.extend({
name: attr()
});
<h1>Welcome to {{appName}}</h1>
<br>
<button {{action "addFilteredUser"}}>Add Filtered User</button>
<button {{action "addUnfilteredUser"}}>Add Unfiltered User</button>
<br><br>
<table width="100%" border=1 valign="top">
<thead style="background: cyan" >
<tr>
<th>All Users ({{data.length}}</th>
<th>Filtered Users ({{filteredData.length}})<br>Computed {{filterComputations}}x</th>
<th>Sorted Users ({{sortedData.length}})<br>Computed {{sortComputations}}x</th>
</tr>
</thead>
<tbody>
<tr>
<td valign="top">{{#display-list data=data as |item|}}{{item.name}} <button {{action "deleteUser" item}}>delete</button>{{/display-list}}</td>
<td valign="top" style="background: yellow">{{#display-list data=filteredData as |item|}}{{item.name}}{{/display-list}}</td>
<td valign="top">{{#display-list data=sortedData as |item|}}{{item.name}}{{/display-list}}</td>
</tr>
</tbody>
</table>
<br>
{{outlet}}
<br>
<br>
<table width="100%" valign="top">
<tbody>
{{#each data as |item index|}}
<tr style="{{{if (odd index) "background: rgba(0, 0, 0, 0.2)"}}}">
<td>
{{yield item index}}
</td>
</tr>
{{/each}}
</tbody>
</table>
{
"version": "0.15.1",
"EmberENV": {
"FEATURES": {}
},
"options": {
"use_pods": false,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js",
"ember": "3.4.3",
"ember-template-compiler": "3.4.3",
"ember-testing": "3.4.3"
},
"addons": {
"ember-data": "3.4.2"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment