Search code examples
javascripthtmlweb-component

my-component.js:24 Uncaught TypeError: window.open is not a function


I have created a simple web component using vanilla js just onclick to open URL on a new window unfortunately I get the following error

my-component.js:24 Uncaught TypeError: window.open is not a function

Here is my web component:

export class MyComponent extends HTMLElement {
  constructor() {
    super();
  }

  connectedCallback() {
    this._render();
    this._attachEventHandlers();
  }

  _render() {
    const container = document.createElement("div");
    container.innerHTML = `
            <div class='app'>
                <button id="open-me">Open</button>
          </div>`;

    const shadowRoot = this.attachShadow({ mode: "open" });
    shadowRoot.appendChild(container);
    }

    _attachEventHandlers() {
        this.shadowRoot.getElementById('open-me').addEventListener('click', () => {
            window.open('www.google.com', "_blank");
        })
    }
}

window.customElements.define("my-component", MyComponent);

usage of this component, just import in your HTML and add it like this

 <my-component></my-component>

What is wrong here?


Solution

  • I would shorten it to:

    customElements.define("my-component", class extends HTMLElement {
      constructor() {
        let button = document.createElement("button");
        button.innerText = "open";
        button.onclick = (evt) => {
          alert("You clicked! " + evt.target.nodeName);
          open('www.google.com', "_blank");
        };
        super().attachShadow({mode:"open"})
               .append(button);
      }
    });
    <my-component></my-component>

    • No need for a Named class definition, when you use it only once
    • no need for export, the Web Component is created in the Global registry
    • No need for the div soup, unless they actually have a purpose.
    • addEventListener only required when you want muliple events on the same element
    • window. for customElements, alert and open not required;
      we're in the Browser, the default is window
    • super sets AND returns the 'this' scope; so can be chained
    • attachShadow sets AND returns this.shadowRoot; so can be chained
    • Learn the power of append over appendChild
      https://developer.mozilla.org/en-US/docs/Web/API/Element/append

    Your open issue can not be related to Web Components; check that statement raw, in the console.

    Here in StackOverflow it says:

    Postscript per comments

    OP was responsible for overriding window.open himself.