Return data from action to component


#1

I use highcharts and I wanted to load data on legend change. so I use on click event in component, than I send action to controller where I get data. And now I need to send it back, to user this.setData(BACKDATA); function in component. I do not want to refresh the chart, only redraw it. Or maybe it’s better to get data from component?

Component:

 events: {
            legendItemClick: function () {
              let chart = this;
              self.triggerAction({
                action:'changeMetric',
                actionContext: chart.name
              });
              this.setData(BACKDATA);
            }

Controller:

changeMetric(val){ let params = {Metric: “active_time”}; let promise = getStoreData(this.get(‘store’), ‘comparetimeframe’, params); }

Thanks


#2

I think there are two options.

Use a service in your component

Inject a service into your component, and have the component ask the service for the data instead of the controller. Then, the controller really doesn’t need to know about the event at all. This would look like:

export default Component.extend({
  dataProvider: Ember.inject.service(),
  actions: {
    legendItemClick: function() {
      var data = this.get('dataProvider').getData(...);
      // Do the minimal update for the data
    }
  }
});

The service would be defined in a file services/data-provider.js (or with pods, at pods/data-provider/service.js). Note that services are singletons, and so the same object would be injected into all instances of your component. I’m guessing this is fine, since controllers are also singleton, but keep this in mind.

Use didUpdateAttrs

Have the controller pass new values to the component through the template, and detect the changes using the hook didUpdateAttrs. This is a bit more complicated, but then the state of the component depends entirely on what is passed to it, which is usually more testable and modular, and less error-prone.

export default Component.extend({
  didUpdateAttrs: function({oldAttrs, newAttrs}) {
    // examine the differences in oldAttrs and newAttrs and take the appropriate minimal action for the change
  },

  actions: {
    legendItemClick: function() {
      this.sendAction('onLegendChanged', ...);
    }
  }
});

export default Controller.extend({
  actions: {
    onLegendChanged: function() {
      this.set('data', ...);
    }
  }
});

// And in your controller's template:
{{your-component data=data onLegendChange=(action 'onLegendChange')}}

Hopefully, I understood your question correctly! Best of luck :slight_smile: