VanillaJS에서 추적된 변수에 접근하는 방법?

다음과 같은 코드가 있습니다:

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}}"
      }
    ]
  }, "*");
});

이 코드는 DModal 내부의 iframe을 변경하여 코드의 언어와 내용을 포함하도록 합니다. 하지만 iFrame이 null이라고 알려주며 addEventListener를 추가하지 못합니다.
다음과 같이 시도해 보았습니다:

<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>

하지만 이것도 작동하지 않았습니다. 이를 수행할 수 있는 방법이 있을까요?


리포지토리 링크:
https://github.com/NateDhaliwal/Discourse-OneCompiler-Code-Runner

gjs에서 작업하고 있는 것 같으니, DOM 렌더링과 레이스 컨디션 문제를 우회하려 하지 말고 glimmer 함수를 사용하면 됩니다. iframe 요소에 glimmer {{on}} modifier를 추가하고, on loaded 함수가 해당 요소에서 실행되도록 하세요.

@action
onIframeLoaded() {
...
}

...
<iframe {{on "load" this.onIframeLoaded}}

그게… 존재해!? 와, 한번 해볼게.

음… 이 에러가 발생했습니다:

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)

코드:

@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>

아, 제 예시가 잘못되었습니다. 함수 참조여야 하므로 괄호 없이 {{on "load" this.onIframeLoaded}}가 되어야 합니다.

답변을 수정했습니다.

음… ESLint에서 Error: 74:13 error 'on' is not defined라는 오류가 나네요. 그리고 문서는 이것이 수정자(modifier)이기 때문에 임포트에 대한 언급이 없어요.
문서가 그렇게 하고 있어서 onIframeLoaded에 event를 매개변수로 추가했어요.

import { on } from "@ember/modifier";를 추가하면 작동할 것입니다.
기존 코드를 참고하여 학습할 수 있는 좋은 장소인 Discourse 소스 코드를 살펴보는 것도 좋은 아이디어입니다.

GitHub - discourse/all-the-plugins · GitHub 과 GitHub - discourse/all-the-themes · GitHub 도 참고하세요.