Search code examples
javascripthtmlweb-component

Can a custom element extend an input element?


Using the web components specification, is it possible to extend a specific type of <input> element?

This question is similar to mine, but it only specifies how to extend a button element, not a text input or any other variant of the <input> tag.

In my case, I'd love to extend a checkbox (<input type="checkbox" />) or a radio button (<input type="radio" />) in order to wrap more complex UI around the same core input element functionality, but I don't see any way to do that using the extends syntax provided by document.registerElement. In my mind it would seem that you should be able to do something like the following:

document.registerElement('x-checkbox', {
    prototype: Object.create(HTMLInputElement.prototype),
    extends: 'input[type=checkbox]'
});

However, this specific case doesn't seem to be documented or explained anywhere that I can find, and I'm fairly confident that example won't work in practice.


Solution

  • The is attribute must be used if you are extending another standard HTML element. Since there is no "checkbox" element, you cannot extend things like input[type=checkbox] or radio. Extend the input element (HTMLInputElement) and specify the type in the createdCallback:

    <body>
        <input is="totally-not-checkbox">   <!-- Custom Checkbox #1 -->
    </body>
    
    var proto = Object.create(HTMLInputElement.prototype);
    proto.createdCallback = function() {
        this.type = "checkbox";
        this.addEventListener("change", this.toggleZoom);
    };
    proto.toggleZoom = function(){
        $(this).toggleClass("zoom");                        //FYI $ is jQuery
    };
    
    var nCB = document.registerElement("totally-not-checkbox", {
        prototype: proto,
        extends: 'input'
    });
    
    document.body.appendChild(new nCB());  //Custom Checkbox #2
    

    Demo: http://jsfiddle.net/DerekL/5utco0en/

    Since the custom element extends from HTMLInputElement, all original properties and methods are inherited. Take a look at this demo: http://jsfiddle.net/DerekL/6gtLp8p5/

    proto.toggleZoom = function(e){
        $(this).toggleClass("zoom");
        console.log(this, this.checked);
    };
    

    this.checked will return the correct checked value just like an original checkbox.