js-integration-examples icon indicating copy to clipboard operation
js-integration-examples copied to clipboard

Add preventClose

Open janwirth opened this issue 4 years ago • 3 comments

class PreventClose extends HTMLElement {
  // set up events
  connectedCallback() {
    // disable on localhost for david's sanity
    if (window.location.host.includes("localhost")) {
      return;
    }
    this.beforeUnloadListener = (event) => {
      event.preventDefault();
      return (event.returnValue =
        "Are you sure you want to exit? There are unsaved changes.");
    };
    addEventListener("beforeunload", this.beforeUnloadListener, {
      capture: true,
    });
  }
  disconnectedCallback() {
    removeEventListener("beforeunload", this.beforeUnloadListener, {
      capture: true,
    });
  }
}

customElements.define("prevent-close", PreventClose);

janwirth avatar Mar 22 '22 09:03 janwirth

This looks like an example of something that should not be done as a Custom Element because it's not actually extending HTMLElement. The web component is being used as a convenience for adding arbitrary javascript via the DOM, it's being added to the DOM, but it doesn't actually have any reason to be in the DOM.

Why not use a port instead?

How web components was originally envisioned was as leaf-node or light-DOM-using components

timcase avatar Mar 22 '22 22:03 timcase

Following arguments for declaring this behavior in the DOM:

  • head tags are in the DOM, we can control the title from the view. The line here is blurry
  • using the port and tracking the state of the outside world requires a lot of glue code and data massaging if you have a big view
  • the knowledge about what needs to be saved before losing it is often available in the view "You have unsaved changes, click here to save". So why not declare the behavior there?
image

janwirth avatar Mar 26 '22 16:03 janwirth