Ember: use controller data in route or how to fetc

2020-08-01 05:58发布

问题:

This question is a follow up on my previous question: Architecture for reusable object in ember

In my app I create multiple charts using an Ember.Component. The daterange for all the charts is controlled by a Daterangepicker which has its own controller etc.. Now the data for each chart is fetched in the IndexRoute (with an ajax call), and the daterange is passed in the query string.

The problem is that I can't seem to figure out how to access the daterange from the IndexRoute. Here's my code:

IndexRoute.js

App.IndexRoute = Ember.Route.extend({

  model: function(){

    var that = this;

    return Ember.Object.extend({
      registrationsData: null,
      registrations: function() {

        var self = this;

        $.ajax({
            url: Routing.generate('ysu_user_api_statistics_registrations', {startDate: that.dateRange.startDate, endDate: that.dateRange.endDate}),
            success: function(data) {

                var labels = [];
                        var values = [];

                        var chartData = {
                            labels : data.labels,
                            datasets : [
                            {
                                data : data.values,
                            }
                            ],
                        };

                        self.set('registrationsData', chartData);

                    }
                });
        }.property(),
    }).create();

  },
    dateRange: Ember.Object.create({
        id: 1,
        startDate: '2013-08-01',
        endDate: '2013-08-31'
  }),
 });

Index.hbs

{{ my-chart title="Registrations" dataBinding=model.registrations registrationsDataBinding=model.registrationsData}}

MyChartComponent.js

App.MyChartComponent = Ember.Component.extend({
  ...
  dataBinding: null,
  registrationsDataBinding: null,
  dateRangeBinding: null,
  modelDateRangeBinding: null,
  chartContext: null,
  myChartController: null,
  didInsertElement: function() {

    /* Create and set controller */
    if (!this.get('myChartController')) {
      myChartController = new App.MyChartController()
      this.set('myChartController', myChartController);
    }

    this.set('chartContext', $(this.get('element')).find('canvas')[0].getContext("2d"));

  },

  drawChart: function() {

    if(this.get('chartContext')) {

        var ctx = this.get('chartContext');

        var options = {
            bezierCurve : false,
            pointDotRadius : 6,
            pointDotStrokeWidth : 4,
            datasetStrokeWidth : 4,
        }

      var myNewChart = new Chart(ctx).Line(this.get('registrationsDataBinding'), options);

    }

  }.observes('registrationsDataBinding', 'myChartController.dateRange'),

});

MyChartController.js

App.MyChartController = Ember.ArrayController.extend({
    container: App.__container__,
    needs: ['daterangepicker'],
    dateRange: 'controllers.daterangepicker.selectedRange',
    dateRangeBinding: 'controllers.daterangepicker.selectedRange',
});

I must admit, this setup feels kinda weird. So ultimately my question is: What would be the correct way to fetch data for my charts based on startDate and endDate set in my DatePickerController?

回答1:

I have been struggling with this problem as well.

In some of my apps, I've needed the URL to control the date range (e.g. a particular month). In these cases, I would created a MonthRoute and a MonthModel - think of it as a monthly report. The MonthModel has a hasMany property of the actual data I wanted to chart:

App.Month = DS.Model.extend({
  companies: DS.hasMany('App.Company')
});

A datepicker would let the user enter a new route, which would fetch (say) the Jan-2013 month model

{
  month: {
    id: 'Jan-2013',
    companies: [
      {name: 'Acme, Inc', revenue: 10425, ...},
      ...
    ]
  }
}

Then, I would set the embedded companies data on my CompaniesController in the setupController hook:

App.MonthRoute = Ember.Route.extend({
  setupController: function(controller, model) {
    controller.set('model', model);
    this.controllerFor('companies').set('model', model.get('companies'));
  }
});

Then, I would do the various array manipulations on my CompaniesController, and make that data available to my charts.

I have some code for this up on github, as well as a demo. I'd be interested to hear your thoughts.



标签: ember.js