<text-field></text-field>
const styles = new CSSStyleSheet();
styles.replaceSync(`
:host::part(number) {
width: 24px;
}
:host(:state(error))::part(text) {
border-color: red;
}`);
class TextField extends HTMLElement {
static formAssociated = true;
#internals;
#shadowRoot;
#text;
#minlength;
constructor() {
super();
// instantiate Element Internals
this.#internals = this.attachInternals();
// attach ShadowDOM
this.#shadowRoot = this.attachShadow({
mode: 'open',
delegatesFocus: true
});
this.#shadowRoot.adoptedStyleSheets.push(styles);
this.#shadowRoot.innerHTML = `
<label>minlength=<input type="number" part="number" min=0></label>
<input type="text" part="text">`;
}
connectedCallback() {
this.#text = this.#shadowRoot.querySelector('input[type="text"]');
this.#min = this.#shadowRoot.querySelector('input[type="number"]');
this.#text.addEventListener('change', () => {
this.#internals.setFormValue(this.#text.value);
this.validate(this.#text.value);
});
this.#min.addEventListener('input', () => {
this.validate(this.#text.value);
});
this.#min.value = 3;
}
validate(newValue) {
if (newValue.length >= this.#min.valueAsNumber) {
this.#internals.setValidity({});
this.#internals.states.delete('error');
return;
}
this.#internals.setValidity({
tooShort: true
}, 'value is too short', this.#text);
this.#internals.reportValidity();
this.#internals.states.add('error');
}
}
customElements.define('text-field', TextField);
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.