making inputs reusable?

Here’s how to do it. First, create a new helper function:

function multiRow(inputs) {
  return function(value) {
    const $inputs = inputs(value);
    
    for(const [name, $input] of Object.entries($inputs)) {
      if(name in value) $input.value = value[name];
    }

    const $view = html`<div>${Object.values($inputs)}`;
    const props = Object.fromEntries(Object.entries($inputs).map(([name, $input]) => [
      name,
      {
        get: () => $input.value,
        enumerable: true,
      },
    ]));
    $view.value = Object.defineProperties({}, props);
    $view.onchange = e => {
      if(e.target === $view) return;
      e.stopPropagation();
      $view.dispatchEvent(new Event('change', {bubbles: true}));
    };

    return $view;
  }
}
  • The function receives a callback, which, when called, returns an object of form elements, where the property names correspond to the desired names in the values object.
  • The function returns a builder function which, when called, constructs a new form row.

Then use it like this:

viewof myList = listInput({input: multiRow(() => ({
  mySelect: DOM.select(['one', 'two']),
  myText: html`<input>`,
})), defaultValue: {mySelect: 'two'}})