I have a main page listing some categories / subcategories. Whenever a subcategory is clicked, the action openSubcategory
is triggered:
// routes/application.js
import Ember from 'ember';
export default Ember.Route.extend({
userSelections: Ember.inject.service('user-selections'),
actions: {
openSubcategory: function(categoryId, subcategoryId) {
var userSelections = this.get('userSelections');
userSelections.set('category', categoryId);
userSelections.set('subcategory', subcategoryId);
this.transitionTo('filter-categories');
},
}
});
To pass the selections to the corresponding controller, I am using a service:
// services/user-selections.js
import Ember from 'ember';
export default Ember.Service.extend({
category: null,
subcategory: null,
init() {
this._super(...arguments);
this.set('category', null);
this.set('subcategory', null);
},
});
Which is evaluated in:
// controllers/filter-categories.js
import Ember from 'ember';
export default Ember.Controller.extend({
userSelections: Ember.inject.service('user-selections'),
init() {
this._super(...arguments);
this.get('userSelections'); // We need to get it so that we can observe it?
// We can not declare the observers, because we need to make sure userSelections is first read
this.addObserver('userSelections.category', function() {
Ember.run.once(this, 'refreshProducts');
});
this.addObserver('userSelections.subcategory', function() {
Ember.run.once(this, 'refreshProducts');
});
},
actions: {
changedCategory: function(selectedCategory) {
this.set('selectedCategory', selectedCategory);
this.get('userSelections').set('category', selectedCategory.value);
},
changedSubcategory: function(selectedSubcategory) {
this.set('selectedSubcategory', selectedSubcategory);
this.get('userSelections').set('subcategory', selectedSubcategory.value);
},
},
refreshProducts: function() {
var userSelections = this.get('userSelections'),
category = userSelections.get('category'),
subcategory = userSelections.get('subcategory');
var products = this.store.filter('product', function(product) {
var catId = parseInt(product.get('category').get('id')),
subcatId = parseInt(product.get('subcategory').get('id'));
if (category && catId !== category) {
return false;
}
if (subcategory && subcatId !== subcategory) {
return false;
}
return true;
});
this.set('model', products);
},
});
Observing the userSelections
(after some hacking, as seen in the comments) works: the actions are properly triggering the refreshProducts
method. But it seems the method is not triggered when coming from the application route, probably because the controllers/filter-categories
is not yet initialized.
(*) According to the documentation there are lots "issues" observerving services.
- Observers and asynchrony
- Observers and object initialization
- Unconsumed Computed Properties Do Not Trigger Observers
- "The injected property is lazy; the service will not be instantiated until the property is explicitly called" (link)
As a result, code needs to be written in a difficult to understand way. Is there a better pattern to share data between routes / controllers than using a service?
Aucun commentaire:
Enregistrer un commentaire