How to get iframe's refreshed src after interacting

Viewed 2882

I have an iframe tag that is linked with a Grafana graph, which supports interaction (zoom in/zoom out on x axis by clicking/double clicking on the iframe).

When I open the url of the iframe's src on a new tab I can interact with the graph and see that my browser's url params keeps refreshing with new from/to values (which indicates the range of the graph's x axis). Unfortunately when it is on an iframe I don't see any changes on the 'src' attribute, on any situation. I need the url parameters changes to apply on other graphs being displayed (sync them all).

How can I solve this situation?

My iframe on Angular's component.html:

<iframe [src]="url_grafana_primary" width="100%" height="300" frameborder="0"></iframe>

Iframe after being rendered:

<iframe _ngcontent-c8="" frameborder="0" height="300" width="100%" src="http://146.250.180.213/grafana/dashboard-solo/script/script_graph.js?scenario_id=rrc_succ_rate&amp;cell_id=ESICAS23B_ESICAS23&amp;refresh=5s&amp;orgId=1&amp;panelId=4&amp;from=1555045266010&amp;to=1555168469864&amp;var-cell_id=ESICAS23B_ESICAS23&amp;var-scenario_id=ESICAS23B_ESICAS23"></iframe>

Some screenshots:

You can see that src keep the same value on both situations.

4 Answers

The attribute of src is not changing, but the location object should behaves the same as it behaves when grafana is outside of the iframe.

You have 2 options,

  1. if the frame of grafana & its parent are served from the same origin, you can access the location object with iframe.contentWindow.location.href.
  2. if they are with different origins, you need to communicate between the frame and its parent, you can use postMessage for that.

check this example: https://robertnyman.com/html5/postMessage/postMessage.html

You can detect the onload event, but to get the URL, you will have to store a cookie or localStorage.

var firstTimeLoad = true; // Because the function will call on the initial page

function iframeLoad(iframe) {
  if (firstTimeLoad) {
    firstTimeLoad = false;
    return;
  }
  alert("New page load");
}
<iframe width="400" height="244" src="https://wooden-utensil.github.io/linkingSite1/" onload="iframeLoad(this)" frameBorder="0"></iframe> <!-- linkingSite1 contains a link (a href) that links to linkingSite2, and vice versa -->

In case when you are not the owner of the content in an iframe, you can't do much. The best you can do is to have a loop (setInterval), that will check the value against the last value you have seen.

<iframe #graph></iframe>
@ViewChild('graph', { static: true }) graph!: ElementRef<HTMLIFrameElement>;

private srcWatcher = new Observable(observer => {
  const interval = setInterval(() => {
    observer.next(this.graph && this.graph.nativeElement && this.graph.nativeElement.src);
  }, 10);

  return () => clearInterval(interval);
}).pipe(
  distinctUntilChanged(),
);

having observable as this one, you can now react to any changes on it.

NOTE: I would also suggest that the observable should run outside of zoneJS if the interval timeout should be low. Otherwise Angular would run global change detection on every interval. By global I mean, that it would check the whole app any all of the subtrees, that uses the default change detection strategy.

You just need to set the src of the iframe to the same old src. You may need to add a query string variable with random number like timestamp to avoid caching issues.

function refresh(){
  var iframe = document.getElementById('myframe');
  iframe.src = iframe.src;
 }
iframe{
width:100%;
height:300px;
}
<p>
 <button onclick="refresh()">Refresh</button>
</p>
<iframe id="myframe" src="https://www.chartjs.org/samples/latest/charts/line/basic.html" frameborder="0"></iframe>

Related