Interact with embedded dashboards

Hi all, I’m trying to embed pre-prepared Grafana dashboards (iframes or otherwise) into an application* and need some means to interact programmatically with those dashboards. Typical interaction will include changing time interval, template variables and to listening on mouse over events to read the current timestamp. Is there a structured way to do that or do I need to dig into the dashboard internals to make this interaction happen? I know I can reload the whole iframe with new url-params but that makes it clunky for the user, I just want to make the dashboards reload their dataseries with new values…

*) the application is providing a view of a complex telecom system, an essential part is to provide interactive statistics as an integrated part of the application. The dashboards are “only” used to present data, as opposed to design dashboards/graphs in the application.

Thx

2 Likes

There is nothing built into Grafana for this use case. You can access an iFrame’s content with JavaScript (as long as you obey all the cross origin rules). Then you can navigate to a page using Angular $location. It does not cause a full page reload when the browser URL is changed.

Here is an example from the Grafana codebase:

        function changeTime() {
            let timeService = angular.element('grafana-app').injector().get('timeSrv');

            let time = timeService.time;
            time.from = 'now-" & oRandom.Next(1, 10) & "h';
            time.to = 'now';        

            timeService.time = time;
            timeService.refreshDashboard();

            console.log(timeService.$location.search());
        }
        
        changeTime();
    

        function changeTemplateId(templateId) {
            let varService = angular.element('grafana-app').injector().get('variableSrv');

            let templateVar = varService.variables.find(x => x.name == 'TemplateId');

            templateVar.current = {text: templateId, value: templateId}

            varService.variableUpdated(templateVar, true);
        }

        changeTemplateId(1);

I’m also facing this issue and eventually figure out how to change grafana template variable programatically. Here is the code that works:

    let contentWindow = this.$refs.iframe.contentWindow; 

    let varService = contentWindow.angular
      .element('grafana-app')
      .injector()
      .get('variableSrv');

    let dashboard = contentWindow.angular
      .element('grafana-app')
      .injector()
      .get('dashboardSrv').dashboard;

    let v = varService.templateSrv.variables.find(
      ({ name }) => name === varName
    );

    if (!!v) {
      varService.setOptionAsCurrent(v, { text: varValue, value: varValue });
      varService.variableUpdated(v, false); // false to update manually via dashboard object

      dashboard.templateVariableValueUpdated();
      dashboard.startRefresh();
    }

How did you bypass the CORS issue?

Encountered the same question,but my situation is in Vue.js…
Is there have any solution about Vue.js? @daniellee

I’m also interested in this point - I’m specifically interested in understanding when there has been a change in the embedded grafana dashboard (eg a change in the time period that is displayed) and how the web app can know about this.

I guess the solution is to listen to events - if so, any pointers to a list of grafana events?

Thanks!

So, we managed to get some variant of this working. The essence of the solution was as follows:

  • use Grafana behind a reverse proxy (see here: Run Grafana behind a reverse proxy | Grafana Labs ) - this gets around CORS issues
  • add listeners to the Angular app to detect activity within the Grafana embedded iframe - we listened for click, keyup and popstate events
  • on activity, perform a check to see if there is a URL change in the Grafana iframe
  • if there is a change, grab the from and to fields from the URL and do whatever magic you need to…

It is probably possible to have more sensible listeners, tuned to specific activity within Grafana, but this approach worked fine for us in a prototype setting.

Hope this helps someone…

There is a way to enable iframe sharing to bypass CORS issue:

If you need a more secure solution you probably have to come up with a custom solution that proxy’s request as described in this article: