Shorthand for extending native DOM element?

295 views Asked by At

As explained in mdn, custom elements may be based on a native element. For Example, <button is="my-button">. What I'm looking for is kind of the opposite syntax. I'd like a shorthand for creating an element whose tag is custom and is based on a native element, such as <purchase-button is="button">. I'm not looking at add functionality to this custom element over what HTMLButtonElement provides. Just the name.

Yet, this doesn't work:

let purchaseButton = document.createElement('purchase-button', { is: 'button' })
document.body.appendChild(purchaseButton)

The resulting element does not extend HTMLButtonElemenet.

2

There are 2 answers

0
Supersharp On BEST ANSWER

It's not possible, and it doesn't exist in the Custom Element specification.

About this requirement, see issue 603 in the specification forum.

Some are discussing similar needs in other issues (for example #509, good luck for the reading...).

As a workaround, define a <purchase-button> custom element into which you insert a <button>. Then you can use a Shadow DOM with the <slot> element to reflect the original content of the <purchase-button>.

customElements.define( 'purchase-button', class extends HTMLElement {
    constructor() {
        super()
        this.attachShadow( { mode: 'open' } )
            .innerHTML = '<button><slot></slot></button>'
    }
} )

PB.onclick = ev => 
  console.info( '[%s] clicked', ev.target.textContent )
<purchase-button id=PB>Pay</purchase-button>

0
sideshowbarker On

Here’s one ugly way:

class PButton extends HTMLElement {}
customElements.define("purchase-button", PButton)
function PurchaseButton () {
    var pb = document.createElement('purchase-button')
    pb.__proto__ = PurchaseButton.prototype
    return pb
}
PurchaseButton.prototype.__proto__ = HTMLButtonElement.prototype
var purchaseButton = PurchaseButton()
purchaseButton.textContent = "Purchase"
purchaseButton.style = window.getComputedStyle(document.querySelector("button")).cssText
document.body.appendChild(purchaseButton)
document.body.appendChild(document.createTextNode(" ⬅ custom <purchase-button>"))
<button>Purchase</button> ⬅ native &lt;button&gt;<p>