Plugins development - dynamically pupulated param file with bucket and metric lists

Hi There,

i would like to use the ng-repeat directive in the param file of a plugin i am trying to develop.
How can i reference the buckets array and the metrics array in there?
i would like to shape the param file (which reflects on the option tabs) based on the selection made by the user in the data tab of the plugin.

any hint or example to pass?


there you go: $scope.vis.aggs{}

Hi @michimau,

did you manage to solve your problem?

In the meantime i have watched the video tutorial (thanks @ppisljar @thomasneirynck @alexfrancoeur ) and, even if i am developing on 5.6.3., i have understood a number of details which i was missing.

I have solved partially.
I cannot figure out how to force the angular binds of ng-repeat to refresh in the template html (the one populating the option tab).

Any clue?

Usually that refresh is handled by angular as part of the digest cycle. Maybe the operation that changes the model does not trigger such a cycle? If it's an asynchronous operation you might have to wrap it in a scope.$apply().

myPlugin.html and myPllugin_controller.html are containing the same div ng-controller.

The refresh is automatic on the first one, but not on the second.
if I force scope.$apply(), the javascript engine complains about the form being already in the refresh phase.

A complete reload of the page, will apply the modification to the controller html file.

I am confused because it looks like a similar functionality is implemented (in a different way as far as i can see in the source code) and working in the stock linechart where the tab axis is reflecting the changes of the tab data.
I cannot reproduce such functionality. It is a limitation of the plugin skeleton design?

Would you be able to link to or paste the controller code that updates the state that the template binds to?

Apologies for a very dirty WIP file. I have tried so many things...

But, there you go:

Thank you for providing the code. I can reproduce the effect. While they don't solve the problem, a few things stand out to me here:

  • The controller is instantiated twice, because the ng-controller directive does not automatically share the instances.
  • For maintainability I would recommend creating a directive each for the visualization and its options with separate controllers.

Regarding the original problem of the lack of re-rendering, I could not confidently come up with a solution. Maybe @timroes, @ppisljar or @thomasneirynck would be so kind as to jump in here and help us out?

havent have time to look into this in depth, but some general pointers:

$scope.$watch(() => {
        return $ => {
          return agg.makeLabel();
      }, () => {
        const schemaTitle = $scope.vis.type.schemas.metrics[0].title;

        const metrics = $scope.vis.aggs.filter(agg => {
          const isMetric = agg.type && agg.type.type === 'metrics';
          return isMetric && agg.schema.title === schemaTitle;

        // update labels for existing params or create new one
        $scope.vis.params.seriesParams = => {
          const params = $scope.vis.params.seriesParams.find(param => ===;
          if (params) {
   = agg.makeLabel();
            return params;
          } else {
            const series = makeSerie(, agg.makeLabel());
            return series;

hope this helps a bit, if not i can take deeper look next week.

Thank you all for the help so far!!

I am using 2 custom arrays vis.params.aggs and vis.params.metrics in combination with vis.aggs, since i need to have two nested ng-repeat in my option file and I can not loop two times over vis.aggs. Probably this is the wrong approach. Naive question: where do you set the ng-controller, i cannot spot any in

However, the context is:
this is a graph plugin where i need to customize the appearance of nodes/links/labels according to the computed metrics.
Therefore in options i need to:
list the buckets dynamically (which will result into nodes) in the option tab, and in each assign the desired metrics to set nodes sizes, label sizes etc.

You would set the controller in the directive's controller property. In the case of the point series @ppisljar linked to there is no controller, just a link function: Due to the tricky semantics of the link function I would recommend using a controller in your case.

this is the best i came up with:

module.controller('graphOptionController', function($scope, $element, $rootScope, Private) {
    $scope.$watchCollection(function() { return $ { return obj.type }); }, function (newVal) {

It is triggered when:

  • a metric or bucket aggregation is added or removed
  • when the typer of metric or the type of bucketing is chosen

what is missing is a watcher which triggers when the field is chosen. Any advise on how to do that?

right now you are only looking at type in your watch ...
in the code snipped i pasted above you can see that internally for bar charts we use agg.makeLabel() ...
makeLabel() will produce text containing aggregation name and field.

you could also look at field name directly:

(in your case, replace agg with obj)

do you have any other outstanding questions from this ticket ? (sorry it took me so long)

and i really suggest to use makeLabel() ... as not all aggregations have field defined, you would then need to handle that on your own, which might break when we add more aggregations to kibana.

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.