Search code examples
javascripthtmldomcustom-element

extending html form element


First time trying to extend a specific html element, in my case a form. I have some experience with "normal" custom elements / web components, derived from HTMLElement.

The base code for demo purposes:

customElements.define('my-form', class extends HTMLFormElement {
    constructor() {
        console.log('my-form()');
        super();
    }

    connectedCallback() {
        console.log('my-form::cc()');
        super.connectedCallback();
    }
}, {extends: 'form'});

If I insert the new element as <my-form>[form content]</my-form>, the element will be an instance of HTMLElement, but not an instance of HTMLFormElement, from which it was derived. Why? Also the code in constructor() and connectedCallback() are never called. Why ? It is definitely not a form, because it doesn't have the .elements propriety.

Using <form is="my-form"> seems to work somehow, constructor and cc() are called, the object is an instance of HTMLFormElement, the only error I get is TypeError: (intermediate value).connectedCallback is not a function at HTMLFormElement.connectedCallback.

Frankly I would prefer the first option (because in the second one I cannot use custom attributes and call it valid html). But what am I doing wrong ?


Solution

  • <form is="my-form"> is the correct and only notation for a Customized Built-In Element (extends HTMLFormElement)

    <my-form> is the notation for an Autonomous Element (extends HTMLElement)

    The latter is the only version of Custom Elements supported in Safari. Apple have, since 2016, stated they will never implement Customized Built-In Elements.

    HTMLFormElement does NOT have a connectedCallback method; that is why you get an error when you call that method on the super Element.

    If you extend from HTMLFormElement and you use <my-form> it is in no way related to your definition; you create an HTMLUnknownElement, which by default is an HTMLElement.

    So the general advice

    Stick to Autonomous Elements extends from HTMLElement (unless you want to keep a polyfill updated yourself for ever and ever)