Skip to content

Instantly share code, notes, and snippets.

@lvl99
Last active February 23, 2017 07:01
Show Gist options
  • Save lvl99/742a113acc8cf4bd8be69c5041b13990 to your computer and use it in GitHub Desktop.
Save lvl99/742a113acc8cf4bd8be69c5041b13990 to your computer and use it in GitHub Desktop.
Filtering and sorting via computed properties
import Ember from 'ember'
export default Ember.Component.extend({
store: Ember.inject.service(),
title: undefined,
location: undefined,
rating: undefined,
inputRatings: [{
label: 'Not rated',
value: 0
},{
label: 'Bad',
value: 1
},{
label: 'Average',
value: 2
},{
label: 'Good',
value: 3
}],
init () {
this._super(...arguments)
this.set('title', this.get('title'))
this.set('location', this.get('location'))
this.set('rating', this.get('rating'))
},
actions: {
submit () {
let newTitle = this.get('title')
let newLocation = this.get('location')
let newRating = this.get('rating')
let ids = this.get('store').peekAll('item').mapBy('id')
let newId = Math.max(...ids) + 1
if (!newTitle || !newLocation || !newRating) {
return
}
var newItem = this.get('store').pushPayload({
data: {
type: 'item',
id: newId,
attributes: {
title: newTitle,
location: newLocation,
created: new Date().getTime(),
rating: newRating
}
}
})
this.set('title', undefined)
this.set('location', undefined)
this.set('rating', undefined)
}
}
})
import Ember from 'ember'
export default Ember.Component.extend({
// Items
items: [],
// Filters to search/sort items by
filters: {
title: '',
location: '',
rating: []
},
inputRatings: [{
label: 'Not rated',
value: 0
},{
label: 'Bad',
value: 1
},{
label: 'Average',
value: 2
},{
label: 'Good',
value: 3
}],
// The filtered items
filteredItems: Ember.computed('items', 'filters.{title,location}', 'filters.rating.@each.enabled', function () {
let items = this.get('items')
// Apply the filters to the items
let filters = this.get('filters')
let checkedRatings = []
for (let propName in filters) {
if (filters.hasOwnProperty(propName) && filters[propName]) {
if (propName === 'rating') {
this.get('filters.rating').forEach((rating) => {
if (rating.enabled) {
checkedRatings.push(rating.value)
}
})
items = items.filter((item) => {
let isInArray = checkedRatings.includes(item.get('rating'))
return isInArray
})
} else {
items = items.filterBy(propName, filters[propName])
}
}
}
console.log('computed.filteredItems', { filters, checkedRatings, items })
// Return the filtered items
return items
}),
// Check if any filters were applied
filtersApplied: Ember.computed.or('filters.{title,location,rating}'),
// What item properties to sort by and the order to sort
sortBy: {
id: true,
created: true,
title: true,
location: true,
rating: true
},
// The currently set sort direction
sortDirection: 'desc',
// This is the sortedDirection that the sortedItems will be sorted by
sortedDirection: Ember.computed('filters.{title,location,rating}', 'sortDirection', 'sortBy', function () {
let sortBy = this.get('sortBy')
let sortDirection = this.get('sortDirection')
let sorting = []
// Sort by filtered properties
for (let propName in sortBy) {
// Add the sortBy filter/prop if it exists, has a filtered value to sort by and is enabled
if (sortBy.hasOwnProperty(propName) && (this.get(`filters.${propName}`) && sortBy[propName])) {
sorting.push(`${propName}:${sortDirection}`)
}
}
// Add the default sorted properties
sorting.push(`id:${sortDirection}`)
sorting.push(`created:${sortDirection}`)
console.log('computed.sortedDirection', { sortBy, sortDirection, sorting })
return sorting
}),
// This is the collection of items to show
sortedItems: Ember.computed.sort('filteredItems', 'sortedDirection'),
init () {
this._super(...arguments)
// Setup observers
this.set('items', this.get('items'))
this.set('filters', this.get('filters'))
this.set('sortBy', this.get('sortBy'))
this.set('sortDirection', this.get('sortDirection'))
// Set up ratings
this.set('filters.rating', [{
value: 0,
enabled: true
},{
value: 1,
enabled: true
},{
value: 2,
enabled: true
},{
value: 3,
enabled: true
}])
},
actions: {
setSortDirection () {
console.log('setSortDirection', {
sortDirection: this.get('sortDirection'),
selectSortDirection: this.$('select option:selected').val()
})
this.set('sortDirection', this.$('select option:selected').val())
}
}
})
import Ember from 'ember';
export default Ember.Controller.extend({
appName: 'Ember Twiddle'
})
import Model from "ember-data/model"
import attr from "ember-data/attr"
export default Model.extend({
title: DS.attr(),
location: DS.attr(),
created: DS.attr(),
rating: DS.attr()
})
import Ember from 'ember'
export default Ember.Route.extend({
model() {
this.get('store').pushPayload({
data: {
type: 'item',
id: 1,
attributes: {
title: 'Test 1',
location: 'Paris',
created: 1234567890000,
rating: 3
}
}
})
this.get('store').pushPayload({
data: {
type: 'item',
id: 2,
attributes: {
title: 'Test 2 of 3',
location: 'New York',
created: 1234567891000,
rating: 2
}
}
})
this.get('store').pushPayload({
data: {
type: 'item',
id: 3,
attributes: {
title: 'Another test 3',
location: 'London',
created: 1234567892000,
rating: 1
}
}
})
return this.get('store').peekAll('item')
}
})
<h2>Items</h2>
{{create-item}}
{{filter-items items=model}}
<h4>Create item</h4>
<label style="display: inline-block">Title:<br/>
{{input type="text" value=title}}</label>
<label style="display: inline-block">Location:<br/>
{{input type="text" value=location}}</label>
<label style="display: inline-block">Rating:<br/>
{{input type="number" min="0" max="2" step="1" value=rating}}</label>
<button {{action "submit"}}>Add new item</button>
<h4>Filter saved items</h4>
<label style="display:inline-block">
Filter by title<br/>
{{input type="text" value=filters.title}}
</label>
<label style="display:inline-block">
Filter by location<br/>
{{input type="text" value=filters.location}}
</label>
<div style="display:inline-block">
Filter by rating<br/>
{{#each inputRatings as |rating index|}}
<div>
<label>
{{input type="checkbox" checked=(mut (get filters.rating (concat index ".enabled")))}}
{{rating.label}}
</label>
</div>
{{/each}}
</div>
<label style="display:inline-block">
Sort direction<br/>
<select value={{sortDirection}} {{action "setSortDirection" on="change"}}>
<option value="asc">Ascending &uarr;</option>
<option value="desc">Descending &darr;</option>
</select>
</label>
{{#if filtersApplied}}
<h3>Found {{sortedItems.length}} items:</h3>
{{else}}
<h3>{{sortedItems.length}} items:</h3>
{{/if}}
{{#each sortedItems as |item|}}
<p>{{item.id}}. {{item.title}} {{item.location}} [rated: {{get inputRatings (concat item.rating ".label")}}] ({{item.created}})</p>
{{/each}}
{
"version": "0.10.6",
"EmberENV": {
"FEATURES": {}
},
"options": {
"use_pods": false,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.js",
"ember": "2.11.0",
"ember-data": "2.11.0",
"ember-template-compiler": "2.11.0",
"ember-testing": "2.11.0",
"ember-truth-helpers": "1.2.0"
},
"addons": {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment