I have this piece of code:
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}}"
}
]
}, "*");
});
It changes the iframe which is in a DModal to include the code’s language and content. However, it tells me that iFrame
is null
, so it could not add addEventListener
to it.
I’ve tried this:
<template>
<DButton
@translatedLabel="Show Modal"
@action={{this.showModal}}
/>
{{#if this.modalIsVisible}}
<DModal @title="Code Compiler" @closeModal={{this.hideModal}}>
<p>Code: {{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>
But that didn’t work as well. Is there a way I can do this?
Link to repo:
Contribute to NateDhaliwal/Discourse-OneCompiler-Code-Runner development by creating an account on GitHub.
Alteras
February 25, 2025, 6:52am
2
Looks like you’re working in gjs, so you can just use glimmer functions instead of trying to work around DOM rendering and race conditions. Add the glimmer {{on}}
modifier with the iframe element and make your on loaded function fire on it.
@action
onIframeLoaded() {
...
}
...
<iframe {{on "load" this.onIframeLoaded}}
2 Likes
That… exists!? Wow, I’ll give it a shot.
Hmm… got this error:
Compile error: Error: /discourse/theme-9718/discourse/components/show-onecompiler: Parse error on line 18:
... {{on "load" this.onIframeLoaded()}}>
-----------------------^
Expecting 'ID', got 'INVALID' (discourse/components/show-onecompiler.gjs)
Code:
@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="Show Modal"
@action={{this.showModal}}
/>
{{#if this.modalIsVisible}}
<DModal @title="Code Compiler" @closeModal={{this.hideModal}}>
<p>Code: {{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"
{{on "load" this.onIframeLoaded()}}>
</iframe>
</DModal>
{{/if}}
</template>
Alteras
February 25, 2025, 7:08am
5
Ah, I messed up my example. It should be {{on "load" this.onIframeLoaded}}
, no parentheses, since it should be a reference to a function.
I’ve edited my reply.
3 Likes
Hmm… it says that Error: 74:13 error 'on' is not defined
in ESLint. And the docs have no mention of an import because it’s a modifier.
I added event
as a parameter to onIframeLoaded
because the docs did that.
Add import { on } from "@ember/modifier";
and this should work.
It’s a good idea to look at the Discourse source code. It’s a good place to learn with existing code.
2 Likes
pfaffman
(Jay Pfaffman)
February 25, 2025, 5:41pm
8
3 Likes