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

**URL:** <https://discuss.elastic.co/t/plugins-development-dynamically-pupulated-param-file-with-bucket-and-metric-lists/106163>\
**Category:** Kibana\
**Created:** [November 2, 2017, 9:54am UTC](https://discuss.elastic.co/t/plugins-development-dynamically-pupulated-param-file-with-bucket-and-metric-lists/106163 "2017-11-02T09:54:44Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![michimau](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/michimau/32/23262_2.png) [@michimau](https://discuss.elastic.co/u/michimau)\
**Post date:** [November 2, 2017, 9:54am UTC](https://discuss.elastic.co/t/plugins-development-dynamically-pupulated-param-file-with-bucket-and-metric-lists/106163/1 "2017-11-02T09:54:44Z")

</div>

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?

best!  
M

---

<div class="post-metadata">

**Author:** ![michimau](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/michimau/32/23262_2.png) [@michimau](https://discuss.elastic.co/u/michimau)\
**Post date:** [November 3, 2017, 8:28am UTC](https://discuss.elastic.co/t/plugins-development-dynamically-pupulated-param-file-with-bucket-and-metric-lists/106163/2 "2017-11-03T08:28:33Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![weltenwort](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/weltenwort/32/53885_2.png) [@weltenwort](https://discuss.elastic.co/u/weltenwort)\
**Post date:** [November 3, 2017, 2:22pm UTC](https://discuss.elastic.co/t/plugins-development-dynamically-pupulated-param-file-with-bucket-and-metric-lists/106163/3 "2017-11-03T14:22:34Z")

</div>

Hi @michimau,

did you manage to solve your problem?

---

<div class="post-metadata">

**Author:** ![michimau](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/michimau/32/23262_2.png) [@michimau](https://discuss.elastic.co/u/michimau)\
**Post date:** [November 8, 2017, 7:15pm UTC](https://discuss.elastic.co/t/plugins-development-dynamically-pupulated-param-file-with-bucket-and-metric-lists/106163/4 "2017-11-08T19:15:06Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![weltenwort](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/weltenwort/32/53885_2.png) [@weltenwort](https://discuss.elastic.co/u/weltenwort)\
**Post date:** [November 9, 2017, 10:24am UTC](https://discuss.elastic.co/t/plugins-development-dynamically-pupulated-param-file-with-bucket-and-metric-lists/106163/5 "2017-11-09T10:24:00Z")

</div>

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()`](https://code.angularjs.org/1.6.4/docs/api/ng/type/%24rootScope.Scope#%24apply).

---

<div class="post-metadata">

**Author:** ![michimau](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/michimau/32/23262_2.png) [@michimau](https://discuss.elastic.co/u/michimau)\
**Post date:** [November 9, 2017, 10:41am UTC](https://discuss.elastic.co/t/plugins-development-dynamically-pupulated-param-file-with-bucket-and-metric-lists/106163/6 "2017-11-09T10:41:20Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![weltenwort](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/weltenwort/32/53885_2.png) [@weltenwort](https://discuss.elastic.co/u/weltenwort)\
**Post date:** [November 9, 2017, 11:24am UTC](https://discuss.elastic.co/t/plugins-development-dynamically-pupulated-param-file-with-bucket-and-metric-lists/106163/7 "2017-11-09T11:24:43Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![michimau](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/michimau/32/23262_2.png) [@michimau](https://discuss.elastic.co/u/michimau)\
**Post date:** [November 9, 2017, 12:06pm UTC](https://discuss.elastic.co/t/plugins-development-dynamically-pupulated-param-file-with-bucket-and-metric-lists/106163/8 "2017-11-09T12:06:36Z")

</div>

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

But, there you go: [https://github.com/michimau/force-plugin/blob/master/public/graph\_controller.js](https://github.com/michimau/force-plugin/blob/master/public/graph_controller.js)

---

<div class="post-metadata">

**Author:** ![weltenwort](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/weltenwort/32/53885_2.png) [@weltenwort](https://discuss.elastic.co/u/weltenwort)\
**Post date:** [November 9, 2017, 3:28pm UTC](https://discuss.elastic.co/t/plugins-development-dynamically-pupulated-param-file-with-bucket-and-metric-lists/106163/9 "2017-11-09T15:28:15Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![ppisljar](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/ppisljar/32/11588_2.png) [@ppisljar](https://discuss.elastic.co/u/ppisljar)\
**Post date:** [November 10, 2017, 6:40am UTC](https://discuss.elastic.co/t/plugins-development-dynamically-pupulated-param-file-with-bucket-and-metric-lists/106163/10 "2017-11-10T06:40:25Z")

</div>

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

- take a look at the [https://github.com/elastic/kibana/blob/5.6/src/core\_plugins/kbn\_vislib\_vis\_types/public/controls/point\_series/series.js](https://github.com/elastic/kibana/blob/5.6/src/core_plugins/kbn_vislib_vis_types/public/controls/point_series/series.js)
- we use a directive for the options
- we $watch `vis.aggs` (not `vis.params.aggs`) in the options tab ... and its not a simple $watch:

```auto
$scope.$watch(() => {
        return $scope.vis.aggs.map(agg => {
          return agg.makeLabel();
        }).join();
      }, () => {
        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 = metrics.map(agg => {
          const params = $scope.vis.params.seriesParams.find(param => param.data.id === agg.id);
          if (params) {
            params.data.label = agg.makeLabel();
            return params;
          } else {
            const series = makeSerie(agg.id, agg.makeLabel());
            return series;
          }
        });
      });

```

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

---

<div class="post-metadata">

**Author:** ![michimau](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/michimau/32/23262_2.png) [@michimau](https://discuss.elastic.co/u/michimau)\
**Post date:** [November 10, 2017, 8:14am UTC](https://discuss.elastic.co/t/plugins-development-dynamically-pupulated-param-file-with-bucket-and-metric-lists/106163/11 "2017-11-10T08:14:20Z")

</div>

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 [https://github.com/elastic/kibana/blob/5.6/src/core\_plugins/kbn\_vislib\_vis\_types/public/controls/point\_series/series.html](https://github.com/elastic/kibana/blob/5.6/src/core_plugins/kbn_vislib_vis_types/public/controls/point_series/series.html)

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.

---

<div class="post-metadata">

**Author:** ![weltenwort](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/weltenwort/32/53885_2.png) [@weltenwort](https://discuss.elastic.co/u/weltenwort)\
**Post date:** [November 10, 2017, 9:27am UTC](https://discuss.elastic.co/t/plugins-development-dynamically-pupulated-param-file-with-bucket-and-metric-lists/106163/12 "2017-11-10T09:27:24Z")

</div>

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: [https://github.com/elastic/kibana/blob/5.6/src/core\_plugins/kbn\_vislib\_vis\_types/public/controls/point\_series/series.js#L11](https://github.com/elastic/kibana/blob/5.6/src/core_plugins/kbn_vislib_vis_types/public/controls/point_series/series.js#L11). Due to the tricky semantics of the link function I would recommend using a controller in your case.

---

<div class="post-metadata">

**Author:** ![michimau](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/michimau/32/23262_2.png) [@michimau](https://discuss.elastic.co/u/michimau)\
**Post date:** [November 15, 2017, 9:50am UTC](https://discuss.elastic.co/t/plugins-development-dynamically-pupulated-param-file-with-bucket-and-metric-lists/106163/13 "2017-11-15T09:50:55Z")

</div>

this is the best i came up with:

```
module.controller('graphOptionController', function($scope, $element, $rootScope, Private) {
    $scope.$watchCollection(function() { return $scope.vis.aggs.map(function(obj) { return obj.type }); }, function (newVal) {
        console.log('graphOptionController');
    });
});

```

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?

---

<div class="post-metadata">

**Author:** ![ppisljar](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/ppisljar/32/11588_2.png) [@ppisljar](https://discuss.elastic.co/u/ppisljar)\
**Post date:** [November 24, 2017, 7:39am UTC](https://discuss.elastic.co/t/plugins-development-dynamically-pupulated-param-file-with-bucket-and-metric-lists/106163/14 "2017-11-24T07:39:41Z")

</div>

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: `agg.params.field.name`

(in your case, replace `agg` with `obj`)

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

---

<div class="post-metadata">

**Author:** ![ppisljar](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/ppisljar/32/11588_2.png) [@ppisljar](https://discuss.elastic.co/u/ppisljar)\
**Post date:** [November 24, 2017, 7:48am UTC](https://discuss.elastic.co/t/plugins-development-dynamically-pupulated-param-file-with-bucket-and-metric-lists/106163/15 "2017-11-24T07:48:40Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [December 22, 2017, 7:48am UTC](https://discuss.elastic.co/t/plugins-development-dynamically-pupulated-param-file-with-bucket-and-metric-lists/106163/16 "2017-12-22T07:48:49Z")

</div>

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