Skip to content

DOM elements in iframe portal are instantiated from top Window.Node instead of the iframe Window.Node #2358

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
bmingles opened this issue Nov 9, 2024 · 1 comment

Comments

@bmingles
Copy link

bmingles commented Nov 9, 2024

Describe the bug

I'm trying to render SolidJS components inside of an iframe using a Portal. The rendering works, but it seems the DOM elements get created from the parent document instead of the iframe document.

import { createSignal, Show, type Component } from 'solid-js';

import styles from './App.module.css';
import { Portal } from 'solid-js/web';

const IFrame = () => {
  // Track the iframe contentDocument
  const [iframeDocument, setIframeDocument] = createSignal<Document | null>(
    null
  );

  // Signal to track results
  const [stats, setStats] = createSignal<{
    fromTop?: boolean;
    fromiFrame?: boolean;
  }>({});

  // Track the iframe contentDocument in a signal once it has loaded
  const onLoad = (e: Event) => {
    const { contentDocument } = e.target as HTMLIFrameElement;
    setIframeDocument(contentDocument);
  };

  const divRef = (ref: HTMLDivElement) => {
    setStats({
      // I don't want this to be true
      fromTop: ref instanceof window.Node,
      // I want this to be true
      fromiFrame: ref instanceof iframeDocument()!.defaultView!.Node,
    });
  };

  return (
    <iframe srcdoc={`<!DOCTYPE html>`} onLoad={onLoad}>
      <Show when={iframeDocument()?.body}>
        <Portal mount={iframeDocument()?.body}>
          <div ref={divRef}>
            This div is inside an iframe. I want the DOM element to be
            instanticated from the iframe document, but it seems to be
            instantiated from the parent document.
          </div>
          <br />
          <div>
            Instantiated from parent: {String(stats().fromTop)}
            <br />
            Instantiated from iframe: {String(stats().fromiFrame)}
          </div>
        </Portal>
      </Show>
    </iframe>
  );
};

const App: Component = () => {
  return (
    <div class={styles.App}>
      <IFrame />
    </div>
  );
};

export default App;

Your Example Website or App

https://stackblitz.com/edit/solidjs-iframe-issue?file=src%2FApp.tsx

Steps to Reproduce the Bug or Issue

Render an iframe with children in a Portal. Inspect any children rendered in the Portal. They are instances of window.Node instead of contentDocument.defaultView.Node

Expected behavior

I would expect there to be a way to render child elements in an iframe that would use the contentDocument for creating DOM elements.

Platform

  • OS: MacOS
  • Browser: Chrome
  • Version: 1.7.6
@ryansolid
Copy link
Member

Yeah this is an interesting one because all the methods are tied to the document. This has reprocussions for iFrames but requires some more thought on how we can do this since JSX can be created anywhere so there is no owner document/context etc.. You could be creating the elements before the iframe even exists yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants