Reputation: 1360
I would like to render content in a new window. This is the component where I am doing it:
export const NewWindowPortal = ({ children }: { children: (props) => ReactNode }) => {
const ref = useRef(null);
const containerEl = useMemo(() => document.createElement("div"), []);
useEffect(() => {
const externalWindow = window.open("", "", "width=600,height=400,left=200,top=200");
externalWindow?.document?.body?.appendChild(containerEl);
}, []);
return (
<>
<BodyShort>This is a new window</BodyShort>
{createPortal(children({ ref }), containerEl)}
</>
);
};
And this is where I am calling this component:
{openInNewWindow && (
<NewWindowPortal>
{(props) => (
<CustomQuillEditor
ref={props.ref}
resize={resize}
readOnly={lesemodus || readOnly}
defaultValue={reformatText(value)}
onTextChange={onTextChange}
/>
)}
</NewWindowPortal>
)}
I can see that the new window opens, but nothing is rendered in it, it just an empty document. I see that if I just send a div as a child:
{openInNewWindow && <NewWindowPortal>{(props) => <div>{props.text}</div>}</NewWindowPortal>}
And change the NewWindowPortal
to render it:
const text = "test";
const containerEl = useMemo(() => document.createElement("div"), []);
useEffect(() => {
const externalWindow = window.open("", "", "width=600,height=400,left=200,top=200");
externalWindow?.document?.body?.appendChild(containerEl);
}, []);
return (
<>
<BodyShort>This is a new window</BodyShort>
{createPortal(children({ text }), containerEl)}
</>
);
Then I get children rendered in NewWindowPortal
. So, the issue is obviously in CustomQuillEditor
:
export const CustomQuillEditor = ({ readOnly, defaultValue, onTextChange, ref, resize }: EditorProps) => {
const containerRef = useRef(null);
useEffect(() => {
const container = containerRef.current;
const editorContainer = container.appendChild(container.ownerDocument.createElement("div"));
const quill = new Quill(editorContainer, {
theme: "snow",
readOnly,
modules: {
history: {},
toolbar: readOnly
? false
: {
container: [
["bold", "italic", "underline", { header: 3 }],
// [{ 'color': "red" }, { 'background': "yellow" }]
],
},
clipboard: {
allowed: {
tags: ["strong", "h3", "h4", "em", "p", "br", "span", "u"],
// attributes: ['href', 'rel', 'target', 'class', "style"]
attributes: [],
},
customButtons: [],
keepSelection: true,
substituteBlockElements: true,
magicPasteLinks: false,
removeConsecutiveSubstitutionTags: false,
},
},
});
ref.current = quill;
if (defaultValue) {
const delta = quill.clipboard.convert({ html: defaultValue });
quill.setContents(delta, "silent");
quill.history.clear();
}
quill.on(Quill.events.TEXT_CHANGE, () => {
if (quill.getLength() <= 1) {
onTextChange("");
} else {
onTextChange(quill.getSemanticHTML().replaceAll("<p></p>", "<p><br/></p>"));
}
});
return () => {
ref.current = null;
container.innerHTML = "";
};
}, [ref]);
return (
<div
spellCheck={false}
className={`ql-top-container ${readOnly ? "readonly" : ""} ${resize ? "resizable" : ""}`}
ref={containerRef}
></div>
);
};
How can I fix this to have CustomQuillEditor
rendered as well?
Upvotes: 0
Views: 36
Reputation: 46
Pass the ownerDocument
to the child component, and use that ownerDocument
when creating quill elements.
Change NewWindowPortal
to pass ownerDocument
to the child component:
return createPortal(children({ ownerDocument: externalWindowRef.current?.document }), containerEl);
Update CustomQuillEditor
to use ownerDocument
when creating elements:
const editorContainer = ownerDocument.createElement("div");
containerRef.current.appendChild(editorContainer);
This will initializes quill in the right context and editor will render properly in the new window.
Upvotes: 0