Accéder aux variables suivies en VanillaJS ?

J’ai ce morceau de 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}}"
    }]
  }, "*");
});

Il modifie l’iframe qui se trouve dans un DModal pour inclure le langage et le contenu du code. Cependant, il me dit que iFrame est null, donc il n’a pas pu ajouter addEventListener à celui-ci.
J’ai essayé ceci :

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

Mais cela n’a pas non plus fonctionné. Y a-t-il un moyen de faire cela ?


Lien vers le dépôt :

Il semble que vous travailliez en gjs, vous pouvez donc simplement utiliser les fonctions glimmer au lieu d’essayer de contourner le rendu DOM et les conditions de concurrence. Ajoutez le modificateur glimmer {{on}} avec l’élément iframe et faites en sorte que votre fonction on loaded se déclenche dessus.

@action
onIframeLoaded() {
...
}

...

<iframe {{on "load" this.onIframeLoaded}}
2 « J'aime »

Ça… existe ?! Wow, je vais essayer.

Hmm… j’ai eu cette erreur :

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>

Ah, j’ai fait une erreur dans mon exemple. Ça devrait être {{on \"load\" this.onIframeLoaded}}, sans parenthèses, car il doit s’agir d’une référence à une fonction.

J’ai modifié ma réponse.

3 « J'aime »

Hmm… il est indiqué Error: 74:13 error 'on' is not defined dans ESLint. Et la documentation ne mentionne aucune importation car c’est un modificateur.
J’ai ajouté event comme paramètre à onIframeLoaded car la documentation le faisait.

Ajoutez import { on } from \"@ember/modifier\"; et cela devrait fonctionner.
C’est une bonne idée de regarder le code source de Discourse. C’est un bon endroit pour apprendre avec du code existant.

2 « J'aime »

Voir aussi GitHub - discourse/all-the-plugins et GitHub - discourse/all-the-themes

3 « J'aime »