简体   繁体   中英

html to include another html

I like the way Angular manage components. I mean separate html, scss and js files. But I don't want to use Angular, Webpack or jQuery. I'm hoping to write a simple web app depending only on the native browser apis. I'm almost there, but the only thing that is blocking me is to include html templates into the index.html. One way probably I could do would be to write a script to append all templates to the end of the index.html. I tested it and it worked well. But I wonder if there's any easier way that I am not aware of. Please note I need zero dependency.

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WSLD</title>
    <script type="module" src="my-summary.js"></script>
    <script type="module" src="my-detail.js"></script>
</head>
<body>
<my-summary></my-summary>
</body>
</html>

<template id="my-summary">
    <my-detail></my-detail>
    <my-detail></my-detail>
</template>

<template id="my-detail">
    <div>hello there</div>
</template>

my-summary.js

customElements.define('my-summary',
    class extends HTMLElement {
        constructor() {
            super();
            const template = document.querySelector('#my-summary').content;
            this.attachShadow({mode: 'open'}).appendChild(template.cloneNode(true));
            // this.appendChild(template.cloneNode(true));

            const details = this.shadowRoot.querySelectorAll('my-detail');
            console.log(details);
            details[0].setAttribute('a', '123');
        }
    }
);

my-detail.js

customElements.define('my-detail',
    class extends HTMLElement {
        constructor() {
            super();
            const template = document.querySelector('#my-detail').content;
            const shadowRoot = this.attachShadow({mode: 'open'}).appendChild(template.cloneNode(true));
            // this.appendChild(template.cloneNode(true));
        }

        static get observedAttributes() {
            return ["a"];
        }

        attributeChangedCallback(name, oldValue, newValue) {
            console.log(name, oldValue, newValue);
        }
    }
);

Server Side Includes (SSI) let you include HTML files into HTML files. It is a mature feature of most web servers. Enable it and put an include statement into your HTML code:

<!--#include file="my-summary.html" -->
<!--#include file="my-detail.html" -->

Sometimes SSI is just enabled for files with the extension ".shtml".

This is the fastest solution, because it does not require additional requests. All HTML code gets delivered with the first request.

Normally when I write WebComponents I create the template tag inside my js file.

for example:

const template = document.createElement('template');
template.innerHTML = `<div>hello there</div>`;

So I have more control of my template.

I attach a link with a well written guide for mastering WebComponents: https://dev.to/thepassle/web-components-from-zero-to-hero-4n4m

I would use the fetch API to grab the content of your template from the server and put the contents inside a DOM node. Something like this:

my-detail.js

(() => {
  let templateContent = null;
  let onLoaded = [];
  (() => {
    let templateContainer = document.createElement("div");
    fetch("./my-detail.html")
      .then(res => res.text())
      .then(text => {
        templateContainer.innerHTML = text;
        templateContent = templateContainer.firstChild.content;
        onLoaded.forEach(cb => cb());
        loaded = true;
    });
  })();
  customElements.define(
    "my-detail",
    class extends HTMLElement {
      loaded = false;
      constructor() {
        super();
        const onLoad = () => {
          this.attachShadow({ mode: "open" }).appendChild(
            templateContent.cloneNode(true)
          );
        };
        if (templateContent != null) {
          onLoad();
        } else {
          onLoaded.push(onLoad);
        }
      }

      static get observedAttributes() {
        return ["a"];
      }

      attributeChangedCallback(name, oldValue, newValue) {
        console.log(name, oldValue, newValue);
      }
    }
  );
})();

my-detail.html

<template id="my-detail">
    <div>hello there</div>
</template>

You can obviously create some small utility function to simplify this logic so don't end up with a ton of duplicate code across your application.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM