Dogoku Dogoku - 4 months ago 16
HTML Question

Clicking label not focusing custom element (webcomponent)

I'm writing a custom

<select>
element using native DOM (no Polymer)

I'm trying to use my element with a
<label>
element and correctly trigger click events to my element when the label is clicked, i.e:

<label>
My Select:
<my-select placeholder="Please select one">...</my-select>
</label>

// or

<label for='mySelect1'>My Select:</label>
<my-select id='mySelect1' placeholder="Please select one">...</my-select>


However this behaviour doesn't to work out of the box, even if I add a tabindex to make it focusable

Here's a stripped down version of the code and a jsfiddle with some basic debugging: https://jsfiddle.net/h56692ee/2/

var MySelectOptionProto = Object.create(HTMLElement.prototype);
document.registerElement('my-select-option', { prototype: MySelectOptionProto});

var MySelectProto = Object.create(HTMLElement.prototype);
MySelectProto.createdCallback = function() {
if (!this.getAttribute('tabindex')) {
this.setAttribute('tabindex', 0);
}
this.placeholder = document.createElement('span');
this.placeholder.className = 'my-select-placeholder';
this.appendChild(this.placeholder);

var selected = this.querySelector('my-select-option[selected]');
this.placeholder.textContent = selected ?
selected.textContent : (this.getAttribute('placeholder') || '');
};
document.registerElement('my-select', { prototype: MySelectProto});

Answer

Only the phrasing content elements can be targeted by <label>.

So you'll have to manage the focus action by yourself if you want to use a non-standard (autonomous custom) element.

Instead you can choose to define a Customized built-in element that will extend the <select> element, as in the following example: https://jsfiddle.net/h56692ee/4/

 var MySelectProto = Object.create( HTMLSelectElement.prototype )
 //...
 document.registerElement('my-select', { prototype: MySelectProto, extends: "select" } )

You'll need to use the is attribute notation for HTML:

<label>
   My Select:
   <select is="my-select" placeholder="Please select one">
       <option>...</option>
   </select>
</label> 

Update More explanations in these 2 posts: here and there.

Comments