1
votes

I'm using custom web components with shadow dom to load an html file into the element, I can't seem to find a way to load it as an html file without having a delay the header scripts and style links.

In other words, scripts are not loading and external css files in the head tag are delayed till after the html is fully loaded.

the html file looks like this:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html lang="en">

<head>
    <title>My Document</title>
    <link href="/MyStyles.css" rel="stylesheet" type="text/css" />
    <script src="/MyScripts.js" type="text/javascript"></script>
</head>

<body>
    <!-- Other Main Tags -->

    <script src="/AnotherScript.js" type="text/javascript"></script>
</body>

</html>

Javascript:


customElements.define('ui-include', class extends HTMLElement {

    async connectedCallback() {
        let ref = this.getAttribute('ref')

        const shadow = this.attachShadow({ mode: 'open' })
        shadow.innerHTML = 'Loading...';

        fetch(`/documentviewer.aspx/GetContent`,
            {
                body: JSON.stringify({ reference: ref }),
                method: "post",
                headers: {
                    'Accept': 'application/json',
                    'Content-Type': 'application/json'
                },
            })
            .then(r => r.json())
            .then(r => {
                // r.d is the response html string (html file example above)
                shadow.innerHTML = r.d ;
            })
            .catch(e => {
                console.error(e)
            })
            .then(() => {
                console.log('done')
            })
    }
})

HTML:

<ui-include ref="Document_123"></ui-include>

After the page is loaded, when inspecting the ui-include. header tag is not showing anymore. like it was unwraped, heres a screenshot:

enter image description here

Please Note that the selected script in the image is /MyScripts.js not /MyScripts

How can I treat the html response string as an actual document and load it into the web component?

2
Danger: You are using an obsolete Doctype that triggers Quirks mode. Causing browsers to simulate bugs found in Netscape 4 and IE 5 is usually undesirable!Quentin
What is inside 'r.d'? Can you share it, may be then I can help you with it.Deepak Dixit
@DeepakDixit i edited my question. its the html response file exampleAli Kleit

2 Answers

1
votes

You can take help of DOM Parser like this:

customElements.define('ui-include', class extends HTMLElement {
    async connectedCallback() {
        let ref = this.getAttribute('ref')
        const shadow = this.attachShadow({ mode: 'open' })
        shadow.innerHTML = 'Loading...';
        fetch(`/documentviewer.aspx/GetContent`, {
                body: JSON.stringify({ reference: ref }),
                method: "post",
                headers: {
                    'Accept': 'application/json',
                    'Content-Type': 'application/json'
                },
            })
            .then(r => r.json())
            .then(r => {
                shadow.children[0].remove();
                const dp = new DOMParser();
                const f = document.createDocumentFragment();
                const pDom = dp.parseFromString(r.d, 'text/html');
                f.appendChild(pDom.documentElement)
                shadow.appendChild(f);
            })
            .catch(e => console.error(e))
            .then(() => console.log('done'));
    }
})
0
votes

How can I treat the html response string as an actual document and load it into the web component?

If you want to transform a string into a document you should use createHTMDocument. But the content a Web Component is not a document but only a DocumentFragment.

For this reason you cannot have or elements in a Custom Element or in a Shadow DOM.

The way you loaded the string with innerHTML is valid as much as using appendChild() with an Element or a DocumentFragment.