r121
r121

Reputation: 2738

How to load a html form in an iframe

I would like to know how to load the HTML form in the iframe in reactjs.

I have one form component that has all the input fields, and I want to load that form component in the iframe. I would like to know how I can do that.

const Form = () => {
  return (
    <>
      <iframe name="iframe-form" title="This is an iframe form." />
    <form target="iframe-form" onSubmit={handleSubmit}>
      <div>
        <label htmlFor="name">Name</label>
        <input
          type="text"
          id="name"
        />
      </div>
      <div>
        <label htmlFor="email">Email</label>
        <input type="email" id="email" />
      </div>
      <button>Submit</button>
    </form>
</>
  );
};

export default Form;

Currently, it's rendering like this. enter image description here

Upvotes: 2

Views: 873

Answers (2)

ksav
ksav

Reputation: 20830

Use ReactDOMServer.renderToString with iframe's srcDoc attribute.

import ReactDOMServer from "react-dom/server";

export default function App() {
  return (
    <div className="App">
      <iframe
        name="iframe-form"
        title="This is an iframe form."
        srcDoc={ReactDOMServer.renderToString(<Form />)}
      />
    </div>
  );
}

const Form = () => {
  return (
    <form target="iframe-form">
      <div>
        <label htmlFor="name">Name</label>
        <input type="text" id="name" />
      </div>
      <div>
        <label htmlFor="email">Email</label>
        <input type="email" id="email" />
      </div>
      <button>Submit</button>
    </form>
  );
};

Edit react iframe with inline content

Upvotes: 1

Gonzalo Cugiani
Gonzalo Cugiani

Reputation: 660

According to the React documentation, 'React Portals' allow us to render children into a DOM node that exists outside of the parent component’s DOM hierarchy. Basically, portals let us render children wherever we want to.

So the large explanation would be create a portal:

ReactDOM.createPortal(child, container)

In this case, the child is a React element, fragment, or string, and the container is the DOM location or node to which the portal should be rendered.

With a React portal, we can choose where to place a DOM node in the DOM hierarchy, the portal’s contents are also considered children of the parent’s virtual DOM.

MyComponent.js

import React from 'react'

function MyComponent() {
    return (
        <div>
            <p style={{color: 'red'}}>Testing to see if my component renders!</p>
        </div>
    )
}

export default MyComponent;

Now, let’s create a file called CustomIframe.js and write the following code:

import React, { useState } from 'react'
import { createPortal } from 'react-dom'

const CustomIframe = ({
  children,
  ...props
}) => {
  const [contentRef, setContentRef] = useState(null)

  const mountNode =
    contentRef?.contentWindow?.document?.body

  return (
    <iframe {...props} ref={setContentRef}>
      {mountNode && createPortal(children, mountNode)}
    </iframe>
  )
}

export default CustomIframe;

We created a ref with the useState() Hook, therefore, once the state is updated, the component will re-render.

We also got access to the iframe document body, then created a portal to render the children passed to iframe in this body instead:

import './App.css';
import CustomIframe from './CustomIframe';
import MyComponent from './MyComponent';
function App() {


  return (
    <CustomIframe title='A custom made iframe'>
        <MyComponent />
      </CustomIframe>
  );
}

export default App;

You can pass any React app or component as a child of CustomIframe, and it should work fine.

The React app or component will become encapsulated, meaning you can develop and maintain it independently.

You can also achieve the same encapsulation as above using a library called react frame component. To install it, run the following command:

npm install --save react-frame-component

Encapsulate your component as follows:

import Frame from 'react-frame-component';

function App() {

  return (
    <div className='App'>
        <p>Iframes in React</p>
        <Frame >
           <MyComponent />
        </Frame>
    </div>
  );
}

export default App;

Upvotes: 2

Related Questions