I am using queryParams on an app to filter search results by category. I am storing all categories in a single queryParam called filter
, separated by |
. (e.g. /app/search?filter=cat1|cat2|cat3
). I’m not using the array queryParam form because it makes the URL “scary” to users.
I want to configure the app such that clicking on category #1 with the example url I just mentioned sends the user to /app/search?filter=cat2|cat3
. Clicking it again would send the user to /app/search?filter=cat1|cat2|cat3
.
So far I have implemented this using an action on my ApplicationRoute:
actions: {
toggle: function(slug) {
var filters = this.controllerFor('categories').toggle(slug);
this.transitionTo('services', {
queryParams: {
filter: filters.length > 0 ? filters.join('|') : null
}
});
}
}
Here is the CategoryController:
Ember.ArrayController.extend({
filtered: [],
toggle: function(value) {
var array = this.get('filtered');
if (!array.contains(value)) {
array.pushObject(value);
} else {
array.removeObject(value);
}
return array;
},
selected: function(key, value) {
// setter
if (arguments.length > 1) {
// if the value is an array, we are receiving slugs from a
// full page load and we can use it directly.
if (!Ember.isArray(value)) {
// otherwise calculate what would happen if we toggled the
// requested filtering item on or off.
value = this.toggle(this.get('filtered'), value);
} else {
// save array of filters
this.set('filtered', value);
}
}
// getter
return this.get('filtered');
}.property('filtered')
});
Here is the ServicesRoute:
Ember.Route.extend({
queryParams: {
filter: {
refreshModel: true
}
},
model: function(params) {
// there has to be a better way to do this
if (!params.filter) {
return [];
} else {
return this.store.find('category', {
slug: params.filter.split('|')
}).then(function(models) {
return models.map(function(model) {
return model.get('slug');
});
});
}
},
setupController: function(controller, slug) {
this.controllerFor('categories').set('selected', slug);
}
});
… and here is what a category link looks like:
<li {{action 'toggle' category.slug}}>{{category.name}}</li>
I’d like to do this with link-to
so there is a proper anchor link for this item. It seems like it should be trivial to calculate a new queryParam based on what the filters would be if the current slug was added or removed, but it definitely isn’t. I’ve looked into extending Ember.LinkView
, creating a custom helper, etc.
At the moment, I don’t see a viable way to do this. Is there one I’m not aware of?