У меня есть тег iframe, связанный с графиком Grafana, который поддерживает взаимодействие (увеличение/уменьшение масштаба по оси X путем нажатия/двойного щелчка по iframe).
Когда я открываю URL-адрес src iframe на новой вкладке, я могу взаимодействовать с графиком и видеть, что параметры URL-адреса моего браузера продолжают обновляться с новыми значениями from/to (что указывает диапазон оси x графика). К сожалению, когда он находится в iframe, я не вижу никаких изменений в атрибуте «src» в любой ситуации. Мне нужно, чтобы изменения параметров URL применялись к другим отображаемым графикам (синхронизируйте их все).
Как я могу решить эту ситуацию?
Мой iframe в компоненте Angular.html:
<iframe [src] = "url_grafana_primary" width = "100%" height = "300" frameborder = "0"></iframe>
Iframe после рендеринга:
<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&cell_id=ESICAS23B_ESICAS23&refresh=5s&orgId=1&panelId=4&from=1555045266010&to=1555168469864&var-cell_id=ESICAS23B_ESICAS23&var-scenario_id=ESICAS23B_ESICAS23"></iframe>
Некоторые скриншоты:
Вы можете видеть, что src сохраняет одно и то же значение в обеих ситуациях.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Атрибут src не меняется, но объект location должен вести себя так же, как если бы графана находилась за пределами iframe.
У вас есть 2 варианта,
iframe.contentWindow.location.href.проверьте этот пример: https://robertnyman.com/html5/postMessage/postMessage.html
Это не связано с Typescript, это API браузера. У вас есть примеры в MDN.
я добавил пример
Хорошо... так что я понял, что механизм "postMessage" работает только в том случае, если целевой URL-адрес готов получить это сообщение, верно? Если да, то, насколько мне известно, я не могу подготовить Grafana (сервер iframe) для ответа на это сообщение, поскольку я его не разрабатывал. Пожалуйста, поправьте меня, если это возможно.
Кроме того, со случайным сообщением я получаю эту ошибку: «Не удалось выполнить« postMessage »в« DOMWindow »: предоставленный целевой источник ('146.250.180.213') не соответствует источнику окна получателя ('локальный хост: 4201 ')».
Если вы не контролируете содержимое iframe, вы не можете postMessage быть родителем, вы правы.
Если фрейм Grafana находится под вашим контролем и вы можете обслуживать его в том же домене, что и родительский фрейм, это позволит вам получить доступ к местоположению без каких-либо проблем.
Вы можете обнаружить событие onload, но чтобы получить URL-адрес, вам нужно будет сохранить файл cookie или 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 -->Спасибо, но код в разделе «загрузка» не вызывается при обновлении содержимого iframe. Пробовал с `` <iframe [(src)] = "url_grafana_primary" onload = "alert('GRAPH LOADED')" id = "primary_iframe" width = "100%" height = "300" frameborder = "0" #primary_iframe> </iframe> `` и это не сработало.
@DenisCandido Я щелкнул правой кнопкой мыши iframe и нажал «Обновить фрейм», и у меня появилось окно предупреждения. Я не знаю, почему он не отображается для вас?
iframe Grafana работает по-другому. Вы можете взаимодействовать с ним, но он не «обновляется». Он обновляет свои значения, но не запускает общее обновление. Я не знаю, как это работает, и сообщество Grafana мне тоже не помогает.
В случае, если вы не являетесь владельцем контента в iframe, вы мало что можете сделать. Лучшее, что вы можете сделать, это создать цикл (setInterval), который будет сравнивать значение с последним значением, которое вы видели.
<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(),
);
Имея observable как этот, вы теперь можете реагировать на любые изменения в нем.
ПРИМЕЧАНИЕ: Я бы также предложил, чтобы наблюдаемый объект выполнялся за пределами zoneJS, если тайм-аут интервала должен быть низким. В противном случае Angular запускал бы обнаружение глобальных изменений на каждом интервале. Под глобальным я подразумеваю, что он будет проверять все приложение, все поддеревья, которые используют стратегию обнаружения изменений по умолчанию.
К сожалению, не работал. srcWatcher никогда не срабатывает.
@DenisCandido Извините, это никоим образом не возможно, это функция безопасности.
Вам просто нужно установить src iframe на тот же старый src. Возможно, вам придется добавить переменную строки запроса со случайным числом, например с отметкой времени, чтобы избежать проблем с кэшированием.
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>
Не могли бы вы привести пример того, как я могу использовать postMessage на Typescript?