CustomElementsV0: How to properly extend a native HTML element?

118 views Asked by At

I would like to create a HTML custom element extending HTMLInputElement and define its default behavior for events such as focus, change, click, keypress etc.

After giving up on CustomElementV1 (the super() call producing an "Illegal constructor" error), I have tried with the CustomElementV0 approach:

var Xinput = Object.create(HTMLInputElement.prototype);
Xinput.createdCallback = ()=>{
  this.addEventListener('change',(e)=>{
    console.info("field changed", e.target);
  });
};
var Xi = document.registerElement('x-input', { prototype: Xinput, extends: 'input'});

The node is created later:

var n = new Xi();

I would have expected that the this variable in the createdCallback function refers to the DOM node that has been created when doing "new Xi()". However, it refers to the Window object and, as a consequence, the change event is registered multiple times and fires once for each element created: Changing a single field will trigger the change event as many times as there are x-input elements in the DOM.

I have observed this behavior with Chrome v54 - v57.

What is the correct way to achieve the expected behavior (i.e. the event firing only once)?

1

There are 1 answers

0
Supersharp On BEST ANSWER

As suggested by the link in comment, you should not use an arrow function to define the createdCallback method because it won't change the this value.

Instead, use the "classical" function() syntax:

Xinput.createdCallback = function () {
  this.addEventListener('change',e=>
    console.info("field changed", e.target)
  );
};