Search code examples
ember.jshighchartsember-dataember-componentsember-controllers

EmberJS 2.7 passing data down into a component is failing


I have read many questions on this problem, but none of them seem to have the issue I have here.

I am using a third-party component (ember-highcharts) which works great except for this snag.

I have a route called dashboard. For now this route is just using dummydata, it is not using the store. This serves to illustrate the problem.

templates/dashboard.hbs

<div>
{{log model}} <-- NOTE this logs the object to the console as expected
{{summary-chart chartData=model}} <-- my component, see below
</div>

routes/dashboard.js

import Ember from 'ember';

export default Ember.Route.extend({
    // this is for testing, normally we get the data from the store
    model: function() {
        return this.get('modelTestData');
    },

    setupController: function(controller, models) {
        this._super(controller, models);
        controller.set('model', models);
    },

    modelTestData: [{
        name: 'gear',
        colorByPoint: true,
        data: [
            {y: 10, name: 'Test1'},
            {y: 12, name: 'Test2'},
            {y: 40, name: 'Test3'}
            ]
    }],

});

templates/components/summary-chart.hbs

{{log model}}  <-- NOTE this logs '**undefined**' to the console NOT expected
{{high-charts chartOptions=summaryOptions content=model}}

components/summary-chart.js

import Ember from 'ember';

export default Ember.Component.extend({

  summaryOptions: {
    chart: {
        plotBackgroundColor: null,
        plotBorderWidth: null,
        plotShadow: false,
        type: 'pie'
    },
    title: {
        text: 'Total weight of gear in each category'
    },
    tooltip: {
        pointFormat: '<b>{point.percentage:.1f}%</b> of {series.name}'
    },
    plotOptions: {
        pie: {
            allowPointSelect: true,
            cursor: 'pointer',
            dataLabels: {
                enabled: false
            },
            showInLegend: true
        }
    }
  }

});

Why is the model undefined and not being passed into summary-chart component? The chart renders (you can see the title) but of course without the data being plotted, because the model is undefined.

If I change the component to this, so the data is 'local' to the component, then the chart is rendered with the data points:

templates/components/summary-chart.hbs

{{high-charts chartOptions=summaryOptions content=summaryData}}

components/summary-chart.js

import Ember from 'ember';

export default Ember.Component.extend({

  summaryOptions: {
    chart: {
        plotBackgroundColor: null,
        plotBorderWidth: null,
        plotShadow: false,
        type: 'pie'
    },
    title: {
        text: 'Total weight of gear in each category'
    },
    tooltip: {
        pointFormat: '<b>{point.percentage:.1f}%</b> of {series.name}'
    },
    plotOptions: {
        pie: {
            allowPointSelect: true,
            cursor: 'pointer',
            dataLabels: {
                enabled: false
            },
            showInLegend: true
        }
    }
  },

  summaryData: [{
    name: 'gear',
    colorByPoint: true,
    data: [
        {y: 10, name: 'Test1'},
        {y: 12, name: 'Test2'},
        {y: 40, name: 'Test3'}
        ]
  }]

});

Note that 'summaryData' is an identical data structure to 'modelTestData', so the chart understands how to plot it.

What I do not understand is why the route/controller combination is NOT passing the model down to the child component.


Solution

  • Why is it always 2 minutes after posting on SO you realise the answer to your own question?

    The key line is "{summary-chart chartData..."

    The model is being 'handed down' to the "chartData" property of the child component (summary-chart), so of course the data structure is bound to 'chartData' property now at this level, no longer to the model property at the dashboard/route level.

    So the solution is to fix the template binding here:

    templates/components/summary-chart.hbs

    {{log chartData}}  <-- NOTE this logs the object now as expected
    {{high-charts chartOptions=summaryOptions content=chartData}}
    

    chartData is now passed into the 'content' property of the 'high-charts' child component, and the chart renders, yay!