jorgebucaran/hyperapp

Multiple apps on single page

collinglass opened this issue · 5 comments

Hey, I’m looking to use this to rewrite my current widget. Our customers add our JavaScript lib to the head tag. And then we inject html CTAs inside DOM elements where they put our CSS classes. Usually 3-4 CTAs per page. Clicking any of these CTAs opens up a modal with an iframe.

what is the best way to accomplish this with hyperapp?

What is a CTA, if I may ask?

Anyway, this doesn’t sound much like the kind of use-case hyperapp is best for. Unless you’re talking about the iframe content - but each iframe will be its own isolated page so using hyperapp in there shouldn’t be a problem

Isn't CTA spelled out "call-to-action", in other words, a button?

Yes. In general, something that we want users to click on or do. Can be just a button, in our case, it can also be an ad-like banner or inline block

Regarding "Multiple apps on single page": It's perfectly valid/feasible to have multiple Hyperapp apps running at the same time on the same page. I personally like to have them run inside dedicated web components. This way, such mini-apps can even be nested. Think <outer-app><inner-app></inner-app></outer-app>.

I've outlined it for you here:

<script type="module">
  import { h, app } from "https://unpkg.com/hyperapp";

  const styleSheets = new CSSStyleSheet();
  styleSheets.replaceSync(`
    :host {
      /* call-to-action styles */
    }
    button {
      /* button styles */
    }
  `);

  class CallToAction extends HTMLElement {
    #dispatch;

    constructor() {
      const shadowRoot = super().attachShadow({ mode: "open" });
      shadowRoot.adoptedStyleSheets = [styleSheets];
      shadowRoot.innerHTML = "<button></button>";
    }

    connectedCallback() {
      this.#dispatch = app({
        init: {
          /* component state */
        },
        view: (state) =>
          h(
            "button",
            {
              /* button attributes */
            },
            h("slot", {})
          ),
        node: this.shadowRoot.firstChild,
      });
    }

    disconnectedCallback() {
      this.#dispatch((state) => undefined);
    }
  }

  customElements.define("call-to-action", CallToAction);
</script>

<call-to-action>CTA</call-to-action>

You can either import Hyperapp from a CDN, like import { h, text, app, memo } from "https://unpkg.com/hyperapp"; and do so in each of your app modules, or you do it once and put Hyperapp into the global scope (yes, you'd soil the window somewhat) via import * as hyperapp from "https://unpkg.com/hyperapp"; window.hyperapp = hyperapp; and then destructure from the global hyperapp object: const { h, text, app, memo } = window.hyperapp;.