Skip to content

Commit 5e7d17f

Browse files
authored
feat: allow lazy loading selectoptions (#21)
1 parent 75cb8fa commit 5e7d17f

2 files changed

Lines changed: 25 additions & 13 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@deltablot/malle",
3-
"version": "2.7.2",
3+
"version": "2.8.0",
44
"description": "Make text elements malleable, without dependencies.",
55
"main": "dist/main.js",
66
"typings": "dist/main.d.ts",

src/main.ts

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,19 @@
55
* https://github.com/deltablot/malle
66
*/
77

8+
// type for lazy loaders
9+
type Lazy<T> = T | Promise<T> | (() => T | Promise<T>);
10+
11+
function isPromise<T>(v: unknown): v is Promise<T> {
12+
return typeof v === 'object' && v !== null && 'then' in v &&
13+
typeof (v as { then?: unknown }).then === 'function';
14+
}
15+
16+
async function resolveLazy<T>(src: Lazy<T>): Promise<T> {
17+
const value = typeof src === 'function' ? (src as () => T | Promise<T>)() : src;
18+
return isPromise<T>(value) ? await value : value;
19+
}
20+
821
// The `InputType` will set the `type` attribute of the generated input element.
922
export enum InputType {
1023
Color = 'color',
@@ -163,7 +176,7 @@ export interface Options {
163176
* selectOptions: Something.getOptions(),
164177
* ```
165178
*/
166-
selectOptions?: Array<SelectOptions> | Promise<Array<SelectOptions>>;
179+
selectOptions?: Lazy<SelectOptions[]>;
167180
// What is the name of the key to use to lookup the values in the selectOptions array?
168181
// @default value
169182
selectOptionsValueKey?: string;
@@ -394,7 +407,7 @@ export class Malle {
394407
}
395408
}
396409

397-
getInput(): HTMLInputElement {
410+
async getInput(): Promise<HTMLInputElement> {
398411
// create the input
399412
let inputElement = 'input';
400413
if (this.opt.inputType === InputType.Textarea) {
@@ -443,14 +456,13 @@ export class Malle {
443456

444457
// add options for a select
445458
if (this.opt.inputType === InputType.Select) {
446-
Promise.resolve(this.opt.selectOptions).then(o => {
447-
o.forEach(o => {
448-
const option = document.createElement('option');
449-
option.value = o[this.opt.selectOptionsValueKey];
450-
option[this.innerFun] = o[this.opt.selectOptionsTextKey];
451-
option.selected = (o.selected ?? false) || this.original[this.innerFun] === o[this.opt.selectOptionsTextKey];
452-
input.appendChild(option);
453-
});
459+
const opts = this.opt.selectOptions ? await resolveLazy(this.opt.selectOptions) : [];
460+
opts.forEach(o => {
461+
const option = document.createElement('option');
462+
option.value = o[this.opt.selectOptionsValueKey];
463+
option[this.innerFun] = o[this.opt.selectOptionsTextKey];
464+
option.selected = (o.selected ?? false) || this.original[this.innerFun] === o[this.opt.selectOptionsTextKey];
465+
input.appendChild(option);
454466
});
455467
}
456468
// listen on keypress for Enter/Escape keys. Note that Escape will only appear with keydown/keyup, not keypress event.
@@ -467,7 +479,7 @@ export class Malle {
467479
/**
468480
* Process the triggering event: replace target element with an input
469481
*/
470-
process(event: Event) {
482+
async process(event: Event) {
471483
this.debug('Event triggered:');
472484
this.debug(event.toString());
473485

@@ -488,7 +500,7 @@ export class Malle {
488500
this.opt.formClasses.forEach(cl => {
489501
form.classList.add(cl);
490502
});
491-
const input = this.getInput();
503+
const input = await this.getInput();
492504
form.appendChild(input);
493505

494506
// now the submit/cancel buttons

0 commit comments

Comments
 (0)