thisbeyond / solid-select

The Select component for Solid.
https://solid-select.com
MIT License
172 stars 18 forks source link

Prevent clearing value on click outside #23

Open clementmas opened 1 year ago

clementmas commented 1 year ago

Is it possible to keep the input value when clicking outside the input instead of automatically clearing it?

From what I understand, clicking outside the input closes the Select and always triggers clearInputValue().

Thanks!

martinpengellyphillips commented 1 year ago

Curious what the use case for this would be?

clementmas commented 1 year ago

It's for a city search autocomplete similar to Photon, Geoapify or even Google Maps. Clicking away does not clear the value.

I'm using createSelect combined with async options. It works great but I'd rather clear the value manually when an option has been selected.

martinpengellyphillips commented 1 year ago

Interesting. I'm not sure preventing clearing the input would be enough for your use case - currently the logic might hide the input entirely as well. This is because a displayed value can be more complex (elements) than the editable text input.

I wonder though; would setting the value on click away solve the same problem. Essentially track the input value (onInput) and then set the value (e.g. initialValue) to that onBlur.

Might be confusing though that on refocus the text isn't editable / positionable. You'd likely need to have a custom Select component to improve that.

clementmas commented 1 year ago

Hi Martin, thanks for your feedback. I'm already using a custom <Select /> component with createSelect.

TravelMap-admin-map-search-autocomplete

I do want to close the result list when clicking away but not clearing the value. At the moment, I don't see any clean way to do it.

import { createSignal, createResource } from 'solid-js';
import { createSelect } from '@thisbeyond/solid-select';
import { debounce } from '@solid-primitives/scheduled';

export default function Select(props) {
  // Copied from solid-select `createAsyncOptions` but adding debounce
  const [inputValue, setInputValue] = createSignal();
  const [asyncOptions] = createResource(inputValue, props.onSearch, {
    initialValue: [],
  });

  const select = createSelect({
    get options() {
      return asyncOptions();
    },
    onInput: debounce(setInputValue, 400),
    onChange: props.onChange,
  });

  return (
    <div ref={select.containerRef}>
      {/* Input */}
      <input
        ref={select.inputRef}
        disabled={select.disabled}
      />

      {/* Result list */}
      <Show when={select.isOpen && !asyncOptions.loading}>
        <div ref={select.listRef}>
          <For each={select.options}>{/*  */}</For>
        </div>
      </Show>
    </div>
  );
}

I might just leave it like that. The rest is working well.

clementmas commented 1 year ago

Hi Martin,

The recent update makes it easier to use createSelect with a custom <Select /> component.

However the value is still being cleared whenever the list is closed: https://github.com/thisbeyond/solid-select/blob/f0ec2c855e372b7e4addfc57958574b5731ad456/src/create-select.tsx#L163

Can it be replaced by setIsActive(false) and move setInputValue('') to the built-in <Select /> component?

I can understand if that's not a priority/concern. If so, I'll find another solution. Thanks!