I'm learning Lit and I want to make some common functionality that can be added either when extending the element or when using html`` to make a TemplateResult.
Example
For example, I have a custom input element which I want to be able to optionally apply a value converter on change.
I've made a simple mixin for this:
/**
* Mixin to to enable value formatting
* On focus, changes shadow dom input value to the elements value
* On blur, changes shadow dom input value to formatted value
*/
export function ValueFormatterMixin(superClass) {
return class extends superClass {
static properties = {
valueFormatter: { type: Function },
};
firstUpdated(changedProperties) {
super.firstUpdated(changedProperties);
this.addEventListener('focus', this.unmaskValue);
this.addEventListener('blur', this.maskValue);
}
maskValue = (evt) => {
if (typeof this.valueFormatter === 'function') {
this.inputElement.value = this.valueFormatter(this.inputElement.value);
}
};
unmaskValue = (evt) => {
this.inputElement.value = this.value;
};
};
}
This lets me apply this when extending my base custom element:
// Focus: show raw entered number
// Blur: show formatted currency value
class CurrencyElement extends ValueFormatterMixin(BasicInput) {
valueFormatter(value) {
return new Intl.NumberFormat('en-US', { style: 'currency' }).format(value);
}
}
The Problem
I've realized I would also like to optionally add a valueFormatter when creating through element through HTML and not creating a custom element for the input field:
return html`
<basic-input ${addValueFormatter((value) => `${value * 100}%`)}>
`;
I do not however want to add the ValueFormatterMixin to the basic-input class. I would like to keep that class as simple as possible, then lazily add on features. Most of the time I will not value formatter on my inputs so I don't want to include that functionally by default.
I do not believe its possible to retroactively add a mixin from a directive though. Is there a way to retroactively upgrade an element to include more functionality without defining a new component?