Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Capturing input value and using it as the selected option #5

Open
Mitchell8210 opened this issue Jan 14, 2020 · 5 comments
Open

Capturing input value and using it as the selected option #5

Mitchell8210 opened this issue Jan 14, 2020 · 5 comments

Comments

@Mitchell8210
Copy link

Hello, I am trying to implement the react-functional-select component into an application that I am working on, I am wondering if there is a way to capture the input from the user and be able to use that value as the selected option. Is this part of the functionality that is built into this component?

I have a list of options that exist already, my goal is to be able to capture the input from the user in the case that what they typed in does not match any of the options that are available in the predefined set.

@based-ghost
Copy link
Owner

Hey, @Mitchell8210 -
Can you provide a simplified code snippet outlining the workflow you're describing? Are you wanting to not display any options and require the user to input an exact match to one of the potential values and auto-select the option instead of requiring an explicit selection?

@IsmailM
Copy link

IsmailM commented Aug 5, 2020

Hey,

Firstly thank you for this library - It has been amazing so far :).

I would also like to do this - i.e. capture the input value and use it as the selected option:

For Example, if I start with 3 options: ['cat', 'dog', 'mouse']

I would like to allow users to type in 'horse' and upon pressing enter, the original options array is expanded to include horse, which would then be selected. (On a page refresh, I would want it to defaults back to the original option selection).

This is working nicely.

However, I am unable to capture the input value with onKeyDown. I have tried to use React References but I haven't had much luck.

This is what I have currently:

import React, { useState, useCallback, useRef } from 'react';
import { Select } from 'react-functional-select';

const initialOptions = [
  { id: 0, val: 'Cat' },
  { id: 1, val: 'Mouse' },
  { id: 2, val: 'Dog' },
];

function SelectColumnFilter() {
  const [currentValue, setCurrentValue] = useState(null);
  const [currentOptions, setCurrentOptions] = useState(initialOptions);
  const selectRef = useRef(null);

  const getOptionValue = useCallback((option) => option.id, []);
  const getOptionLabel = useCallback((option) => option.val, []);

  const onOptionChange = useCallback((option) => {
    if (option != null) {
      setCurrentValue(option.val);
    } else {
      setCurrentValue(null);
    }
  }, []);

  const onKeyDown = useCallback((e) => {
    var keycode = e.keyCode ? e.keyCode : e.which;
    if (keycode == '13') {
      console.log(e);
      console.log(selectRef.current);

      // I would like to get the current inputted value here.
      const newOption = { id: currentOptions.length, val: 'Horse' };
      const nextOptions = [...currentOptions, newOption];
      setCurrentOptions(nextOptions)
    }
  }, []);

  return (
      <Select
        ref={selectRef}
        options={currentOptions}
        onOptionChange={onOptionChange}
        getOptionValue={getOptionValue}
        getOptionLabel={getOptionLabel}
        onKeyDown={onKeyDown}
        initialValue={currentValue}
      />
  );
}

export default SelectColumnFilter;

@based-ghost
Copy link
Owner

@IsmailM - I just recently published changes for v2.7.1 that should help address the scenario you outline. So, once updating to the latest version, your example above can be changed to the revised snippet below. A few key things to note, the onKeyDown callback property now gets the value of the input control and the currently focused option forwarded to it. The focusedOption param can come into play in case you want to make sure the currently entered search input does not match any other options (e.g. that it is unique) and you can check for that by using focusedOption.index === -1 which will be true if none of the current menuOptions is focused in the menu list. Also, if all the conditions are met, it may be a good idea to use e.preventDefault(), so that the normal handler does not get executed (although, this may not matter much in this scenario).

import React, { useState, useCallback, useRef } from "react";
import { Select } from "react-functional-select";

const initialOptions = [
  { id: 0, val: "Cat" },
  { id: 1, val: "Mouse" },
  { id: 2, val: "Dog" },
];

function SelectColumnFilter() {
  const [currentValue, setCurrentValue] = useState(null);
  const [currentOptions, setCurrentOptions] = useState(initialOptions);
  const selectRef = useRef(null);

  const getOptionValue = useCallback((option) => option.id, []);
  const getOptionLabel = useCallback((option) => option.val, []);

  const onOptionChange = useCallback((option) => {
    if (option != null) {
      setCurrentValue(option.val);
    } else {
      setCurrentValue(null);
    }
  }, []);

  const onKeyDown = useCallback((e, input, focusedOption) => {
    var keycode = e.keyCode ? e.keyCode : e.which;
    if (keycode === "13" && input && focusedOption.index === -1) {
      e.preventDefault();
      
      setCurrentOptions((prevOptions) => [
        ...prevOptions,
        { id: prevOptions.length, val: input },
      ]);
    }
  }, []);

  return (
    <Select
      ref={selectRef}
      options={currentOptions}
      onOptionChange={onOptionChange}
      getOptionValue={getOptionValue}
      getOptionLabel={getOptionLabel}
      onKeyDown={onKeyDown}
      initialValue={currentValue}
    />
  );
}

export default SelectColumnFilter;

@IsmailM
Copy link

IsmailM commented Aug 10, 2020

This looks amazing! Thank you very much for taking the time to implement this 👍

@based-ghost
Copy link
Owner

@IsmailM - no problem, let me know if you find any issues with the recent changes. Thanks for the feedback and insights!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants