react-select Creatable: override default behavior upon pressing Enter key

Viewed 364

I'm using react-select Creatable for my project, and I need to override its default behavior. Currently whenever the user types something in and presses Enter key, it gets added as a new option.

Is there a way to change it to "whenever the user types something in and presses Space bar, it gets added as a new option"?

1 Answers

If you just do

onKeyDown={(e) => {
  if (e.key === "Enter") {
    e.preventDefault();
    e.stopPropagation();
  }
}}

...in your component, that'll stop the Enter key from doing anything. To get the space bar to create a new entry, I think you might want to make a KeyDown handler:

function handleKeyDown(e) {
  if (e.key === "Enter") {
    e.preventDefault();
    e.stopPropagation();
  }
  if (e.key === "Space") {
    handleChange();
}
// in component:
onKeyDown={handleKeyDown}

But I have not tried it yet.

Edit: Solution to keep Enter key from submitting a form the CreatableSelect is embedded within, while still allowing Enter to do react-select's default "create a new entry" behavior:

export function TagEditor({data, handleSave}) {
  const [newValues, setNewValues] = useState(...our data mgr);
  const [lastKey, setLastKey] = useState('');

  const handleChange = (newValue) => {
    setNewValues(newValue);
  };

  function handleKeyDown(e) {
    /* React Select hack for pages where tags are inside a form element:
      Default CreatableSelect functionality is that Enter key creates
      the new tag. So we let that happen, but if they hit Enter again,
      we kill it so the form doesn't submit. Yes, it's hack-y.
    */
    switch (e.key) {
      case 'Enter':
        if (lastKey === 'Enter') {
          e.preventDefault();
          e.stopPropagation();
        }
        setLastKey('Enter');
        break;
      default:
        setLastKey('');
    }
  }

  return <CreatableSelect
    aria-label="Add Tags"
    autoFocus={true}
    blurInputOnSelect={false}
    defaultValue={...our data manager function}
    inputId="tagmanager"
    isClearable={false}
    isMulti
    name="my_field_name"
    onBlur={(e) => {
      e.preventDefault();
      e.stopPropagation();
      handleSave(newValues);
    }}
    onChange={handleChange}
    onKeyDown={handleKeyDown}
    openMenuOnFocus={true}
    options={data}
    placeholder="Select or type new..."
    searchable
    styles={our styles...}
  />;
}

Note this hack is needed because we're using stateless functional components, and react-select is still a state-full class component.

Related