У меня есть следующий фрагмент кода:
let iFrame = document.getElementById('oc-editor');
iFrame.addEventListener('load', function() {
iFrame.contentWindow.postMessage({
eventType: 'populateCode',
language: "{{this.codeLang}}",
files: [
{
"name": "file.{{this.codeLang}}",
"content": "{{this.codeLang}}"
}
]
}, "*");
});
Он должен изменять iframe, находящийся внутри DModal, чтобы добавить язык и содержимое кода. Однако я получаю ошибку, что iFrame равен null, поэтому к нему нельзя добавить обработчик addEventListener.
Я пробовал следующее:
<template>
<DButton
@translatedLabel="Показать модальное окно"
@action={{this.showModal}}
/>
{{#if this.modalIsVisible}}
<DModal @title="Компилятор кода" @closeModal={{this.hideModal}}>
<p>Код: {{this.getCode}}</p>
<iframe
frameBorder="0"
height="450px"
src="https://onecompiler.com/embed/{{this.codeLang}}"
width="100%"
id="oc-editor"
title="OneCompiler Code Editor"
listenToEvents="true">
</iframe>
<script>
let iFrame = document.getElementById('oc-editor');
iFrame.addEventListener('load', function() {
iFrame.contentWindow.postMessage({
eventType: 'populateCode',
language: "{{this.codeLang}}",
files: [
{
"name": "file.{{this.codeLang}}",
"content": "{{this.codeLang}}"
}
]
}, "*");
});
</script>
</DModal>
{{/if}}
</template>
Но это тоже не помогло. Есть ли способ решить эту задачу?
Ссылка на репозиторий:
Contribute to NateDhaliwal/Discourse-OneCompiler-Code-Runner development by creating an account on GitHub.
Alteras
(Steven Chang)
25.Февраль.2025 06:52:31
2
Похоже, вы работаете в gjs, поэтому вместо попыток обойти рендеринг DOM и состояния гонки можно просто использовать функции glimmer. Добавьте модификатор glimmer {{on}} к элементу iframe и привяжите к нему вашу функцию on loaded.
@action
onIframeLoaded() {
...
}
...
<iframe {{on "load" this.onIframeLoaded}}
Такое вообще существует!? Вау, я попробую.
Хм… получил эту ошибку:
Ошибка компиляции: Ошибка: /discourse/theme-9718/discourse/components/show-onecompiler: Ошибка синтаксического анализа на строке 18:
... {{on "load" this.onIframeLoaded()}}>
-----------------------^
Ожидается 'ID', получено 'INVALID' (discourse/components/show-onecompiler.gjs)
Код:
@action
onIframeLoaded() {
let iFrame = document.getElementById('oc-editor');
iFrame.contentWindow.postMessage({
eventType: 'populateCode',
language: "{{this.codeLang}}",
files: [
{
"name": "file.{{this.codeLang}}",
"content": "{{this.codeLang}}"
}
]
}, "*");
return;
}
<template>
<DButton
@translatedLabel="Показать модальное окно"
@action={{this.showModal}}
/>
{{#if this.modalIsVisible}}
<DModal @title="Компилятор кода" @closeModal={{this.hideModal}}>
<p>Код: {{this.getCode}}</p>
<iframe
frameBorder="0"
height="450px"
src="https://onecompiler.com/embed/{{this.codeLang}}"
width="100%"
id="oc-editor"
title="Редактор кода OneCompiler"
listenToEvents="true"
{{on "load" this.onIframeLoaded()}}>
</iframe>
</DModal>
{{/if}}
</template>
Alteras
(Steven Chang)
25.Февраль.2025 07:08:03
5
Ах, я ошибся в примере. Должно быть {{on "load" this.onIframeLoaded}}, без скобок, так как это должна быть ссылка на функцию.
Я отредактировал свой ответ.
Хм… в ESLint сообщается об ошибке: Error: 74:13 error 'on' is not defined. В документации нет упоминания об импорте, так как это модификатор. Я добавил event в качестве параметра для onIframeLoaded, потому что так сделано в документации.
Добавьте import { on } from "@ember/modifier";, и всё должно заработать.
Хорошая идея — посмотреть исходный код Discourse. Это отличное место для обучения на основе существующего кода.
pfaffman
(Jay Pfaffman)
25.Февраль.2025 17:41:17
8