ajax - Ember: Fetching data for objects that depend on each other -
i'm trying build front-end metrics tool ember. code i've written far has been influenced eviltrout's emberreddit application
https://github.com/eviltrout/emberreddit
the goal have 2 classes depend on each other: metrics , filters.
1) once application initializes, filters, instances of filter-class, loaded server. once filters have loaded, displayed checkboxes on screen. after that, metrics objects should take filters parameters , query server data.
2) once user changes checkboxes , updates filter objects, application should take filters parameters again , fetch new metrics data server.
my problem don't know how handle dependencies between these 2 sets of objects asynchronous ajax calls. @ it's current state, application doesn't finish loading filters when starts loading metrics. therefore, filters don't passed parameters metrics ajax-call.
my question is: what's best way ember? there surely has way handle order of ajax calls. intuition manually adding observers isn't way go.
here models of application:
//filter models var defaultfilters = ['dates', 'devices']; //set filter class. filter object multiplied each filter. app.filter = ember.object.extend({ //capitalize first letter title filtertitle: function() { return this.get('id').charat(0).touppercase() + this.get('id').slice(1); }.property('id'), //set attribute see if filter has loaded loadedfilter: false, //create method load filter values server loadvalues: function() { var filter = this; return ember.deferred.promise(function (p) { if (filter.get('loadedfilter')) { p.resolve(filter.get('values')); } else { p.resolve($.getjson("http://127.0.0.1:13373/options/" + filter.get('id')).then(function(response) { var values = ember.a(); response[filter.get('id')].foreach(function(value) { values.push(value); }); filter.setproperties({values: values, loadedfilter: true}); return values; })) }})} } ); //reopen class create "all" method returns instances of filter class app.filter.reopenclass({ all: function() { if (this._all) {return this._all; } var = ember.a(); defaultfilters.foreach(function(id) { all.pushobject(app.filter.create({id: id})); }); this._all = all; return all; }}); //create filters array store filters. app.filters = app.filter.all(); //metric models app.metric = ember.object.extend({ metrictitle: function() { return this.get('id').charat(0).touppercase() + this.get('id').slice(1); }.property('id'), loadedmetric: false, filtersbinding: 'app.filters', loadvalues: function() { var metric = this; var filters = metric.get('filters'); if (filters.get('loadedfilters')) console.log('loading metrics'); return ember.deferred.promise(function (p) { if (metric.get('loadedmetric')) { p.resolve(metric.get('values')); } else { p.resolve( console.log('sending ajax'), $.ajax({ url: "http://127.0.0.1:13373/" + metric.get('id') + "/", data: json.stringify(metric.get('filters')), }).then(function(response) { var values = ember.a(); response[metric.get('id')].foreach(function(value) { values.push(value); }); metric.setproperties({"values": values, "loadedmetric": true}); return values; })) }})} }); app.metric.reopenclass({ findbyview: function(searchview) { if (this._metrics) {return this._metrics; } var metrics = ember.a(); defaultmetricssettings.foreach(function(metric) { if (metric.view == searchview) metrics.pushobject(app.metric.create({id: metric.id},{view: metric.view}, {calculation: metric.calculation}, {format: metric.format}, {width: metric.width})); }); this._metrics = metrics; return metrics; } });
and here routes:
app.applicationroute = ember.route.extend({ //set application routes model filters model: function() { return app.filter.all(); }, //after filter has loaded, let's load values aftermodel: function(model) { return model.foreach(function(item) { item.loadvalues(); }); }, //create controller called applicationcontroller , pass filter model setupcontroller: function(controller, filter) { controller.set('model', filter); } }); app.dashboardroute = ember.route.extend({ model: function() { return app.metric.findbyview('dashboard'); }, aftermodel: function(model) { return model.foreach(function(item) { item.loadvalues(); }); }, setupcontroller: function(controller, metric) { controller.set('model', metric); } });
controllers:
app.applicationcontroller = ember.arraycontroller.extend({ //applicationcontroller controls filters. let's create controller handle each instance of filter itemcontroller: 'filter' }); app.filtercontroller = ember.objectcontroller.extend({ //this sets titleid property used binding html attributes in template. stupid way this. titleid: function() { return "#" + this.get('filtertitle');}.property('filtertitle') });
your aftermodel
hook in sequence of dependent promises. current implementation returning immediately, instead chain promise , return last promise result of hook. router wait whole set of calls complete before continuing setupcontroller
.
aftermodel: function(model) { var promise; model.foreach(function(item)) { if (promise) { promise = promise.then(function() { item.loadvalues(); }); } else { promise = item.loadvalues(); } } return promise; }
i'm not sure how many of calls have, may want batch of these reduce number of http requests.
Comments
Post a Comment