Giter Site home page Giter Site logo

tbleckert / react-select-search Goto Github PK

View Code? Open in Web Editor NEW
675.0 11.0 149.0 13 MB

⚡️ Lightweight select component for React

Home Page: https://react-select-search.com

License: MIT License

JavaScript 89.51% HTML 0.35% CSS 10.14%
selectbox react lightweight search dropdown select javascript component

react-select-search's Introduction

⚠️ Looking for maintainers

First of all, I want to thank you all for the amazing support over the years. This was one of my first open source projects and also my first successful one. I am beyond grateful for all the 33! contributors, wouldn't have been possible to run this project without you.

A lot happened last year. I had my first born son, I had a few time consuming freelance gigs and a few startups that grew. This took time away from open source and I feel I can't do this component justice anymore. Not by myself at least.

I still believe in a tiny, super fast and zero-dependency select component. If there's anyone out there that wants to co-maintain this with me, please reach out to discuss the next steps. Send me an email at [email protected] or hit me up on Twitter

React Select Search

Coverage Status

Features

  • Lightweight, with zero dependencies
  • Accessible
  • Headless mode
  • Basic HTML select functionality, including multiple
  • Search/filter options
  • Async options
  • Apply renderers to change markup and behavior
  • Keyboard support
  • Group options with group names, you can search group names
  • Fully stylable

Install

Install it with npm (npm i react-select-search) or yarn (yarn add react-select-search) and import it like you normally would.

Quick start

import SelectSearch from 'react-select-search';

/**
 * The options array should contain objects.
 * Required keys are "name" and "value" but you can have and use any number of key/value pairs.
 */
const options = [
    {name: 'Swedish', value: 'sv'},
    {name: 'English', value: 'en'},
    {
        type: 'group',
        name: 'Group name',
        items: [
            {name: 'Spanish', value: 'es'},
        ]
    },
];

/* Simple example */
<SelectSearch options={options} value="sv" name="language" placeholder="Choose your language" />

For more examples, you can take a look in the stories directory.

You will also need some CSS to make it look right. Example theme can be found in style.css. You can also import it:

import 'react-select-search/style.css'

Use with SSR

For use with SSR you might need to use the commonjs bundle (react-select-search/dist/cjs). If you want to utilise the example theme (style.css) you need to check if your build script manipulates class names, for example minifies them. If that's the case, you can use CSS modules to get the class names from the style.css file and apply them using the className object. Example can be seen here as well as here https://react-select-search.com/?path=/story/custom--css-modules.

Headless mode with hooks

If you want complete control (more than styling and custom renderers) you can use hooks to pass data to your own components and build it yourself.

import React from 'react';
import { useSelect } from 'react-select-search';

const CustomSelect = ({ options, value, multiple, disabled }) => {
    const [snapshot, valueProps, optionProps] = useSelect({
        options,
        value,
        multiple,
        disabled,
    });

    return (
        <div>
            <button {...valueProps}>{snapshot.displayValue}</button>
            {snapshot.focus && (
                <ul>
                    {snapshot.options.map((option) => (
                        <li key={option.value}>
                            <button {...optionProps} value={option.value}>{option.name}</button>
                        </li>
                    ))}
                </ul>
            )}
        </div>
    );
};

Configuration

Below is all the available options you can pass to the component. Options without defaults are required.

Name Type Default Description
options array See the options documentation below
getOptions function null Get options through a function call, can return a promise for async usage. See get options for more.
filterOptions array null An array of functions that takes the last filtered options and a search query if any. Runs after getOptions.
value string, array null The value should be an array if multiple mode.
multiple boolean false Set to true if you want to allow multiple selected options.
search boolean false Set to true to enable search functionality
disabled boolean false Disables all functionality
closeOnSelect boolean true The selectbox will blur by default when selecting an option. Set this to false to prevent this behavior.
debounce number 0 Number of ms to wait until calling get options when searching.
placeholder string empty string Displayed if no option is selected and/or when search field is focused with empty value.
id string null HTML ID on the top level element.
autoComplete string, on/off off Disables/Enables autoComplete functionality in search field.
autoFocus boolean false Autofocus on select
className string, object select-search-box Set a base class string or pass a function for complete control. Se custom classNames for more.
renderOption function null Function that renders the options. See custom renderers for more.
renderGroupHeader function null Function that renders the group header. See custom renderers for more.
renderValue function null Function that renders the value/search field. See custom renderers for more.
emptyMessage React node null Set empty message for empty options list, you can provide render function without arguments instead plain string message
onChange function null Function to receive and handle value changes.
onFocus function null Focus callback.
onBlur function null Blur callback.

The options object

The options object can contain any properties and values you like. The only required one is name.

Property Type Description Required
name string The name of the option Yes
value string The value of the option Yes, if the type is not "group"
type string If you set the type to "group" you can add an array of options that will be grouped No
items array Array of option objects that will be used if the type is set to "group" Yes, if type is set to "group"
disabled boolean Set to true to disable this option No

Custom class names

If you set a string as the className attribute value, the component will use that as a base for all elements. If you want to fully control the class names you can pass an object with classnames. The following keys exists:

  • container
  • value
  • input
  • select
  • options
  • row
  • option
  • group
  • group-header
  • is-selected
  • is-highlighted
  • is-loading
  • is-multiple
  • has-focus

Custom renderers

If CSS isn't enough, you can also control the HTML for the different parts of the component.

Callback Args Description
renderOption optionsProps: object, optionData: object, optionSnapshot: object, className: string Controls the rendering of the options.
renderGroupHeader name: string Controls the rendering of the group header name
renderValue valueProps: object, snapshot: object, className: string Controls the rendering of the value/input element

The optionProps and the valueProps are needed for the component you render to work. For example:

<SelectSearch renderValue={(valueProps) => <input {...valueProps} />} />

Monkeypatch it if you need to but make sure to not remove important props.

The optionSnapshot is an object that contains the object state: { selected: bool, highlighted: bool }.

Get options

You can fetch options asynchronously with the getOptions property. You can either return options directly or through a Promise.

function getOptions(query) {
    return new Promise((resolve, reject) => {
        fetch(`https://www.thecocktaildb.com/api/json/v1/1/search.php?s=${query}`)
            .then(response => response.json())
            .then(({ drinks }) => {
                resolve(drinks.map(({ idDrink, strDrink }) => ({ value: idDrink, name: strDrink })))
            })
            .catch(reject);
    });
}

The function runs on each search query update, so you might want to throttle the fetches. If you return a promise, the class is-loading will be applied to the main element, giving you a chance to change the appearance, like adding a spinner. The property fetching is also available in the snapshot that is sent to your render callbacks.

Contributors

Made with contrib.rocks.

react-select-search's People

Contributors

alihamuh avatar andruc avatar armanio avatar bruno-gouveia avatar chuksjoe avatar citius avatar coxdn avatar cxdn0 avatar davidangel avatar dependabot[bot] avatar dfdeagle47 avatar ecarradal avatar govindsartaj avatar hiphapis avatar janv avatar jwmann avatar manvydasu avatar marcsigot3b avatar marsonparulian avatar mrf345 avatar nihaals avatar nikolaik avatar nipodemos avatar ogimle avatar patrick91 avatar spenceraung avatar tbleckert avatar ttomppa avatar xedef avatar yhnavein avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-select-search's Issues

Keeping data not in search

Is it possible for the user to enter customized data? For example if they're typing and the option they're looking for is not in the selection box, then they can still type it in. This way it could be used as more of a search box with suggestions from the selection rather than the other way around.

input 'deselect'

Have a new issue that I'm hoping will be as quick to resolve as the last:

When I select an option the input is populated, but focus remains on the field and you can't actually see the text. If I click elsewhere on the page, then it shows, but without the click it makes for a wonky UX. Any thoughts?

cannot select the first item with keyboard

Chrome 51, Firefox 46, Safari 9.0.3 on Mac OS 10.10.5

  • visit demo page
  • click the country selection field
  • type ger
  • press down key once to focus Germany
  • press enter

Result: Nothing happens
Expected behaviour would be that it selects Germany as it does when clicking the item.

suggest: complete the docs

I have read the docs, but can't find how to import and option's format.

maybe like this:

import SelectSearch from 'react-select-search';

const options = [{name: 'Sweden', value: 'SE'}, {name: 'Italy', value: 'IT'}];

render() {
  return (
    <SelectSearch name="country" options={options} value="SE" />
  );
}

Implement with Typescript

Hi, when I tried react-select is a bit complicated for me and looks like a big bundled. So I searched this package and try it, but I have problem in typing of Typescript.
I would like to ask is there's any support for Typescript?

Error:(.., ..) TS7016: Could not find a declaration file for module 'react-select-search'. '../node_modules/react-select-search/dist/index.js' implicitly has an 'any' type.
  Try `npm install @types/react-select-search` if it exists or add a new declaration (.d.ts) file containing `declare module 'react-select-search';`

package.json

...
"react": "^16.8.6",
"react-select-search": "^0.10.2",
...

I'm sorry I'm still beginner

Feedback message when no search results found

Currently when no matched results found, the component doesn't show any feedback message.

An empty box, as it's shown in the official demo.

Is it possible to add a feedback message, something like: "No results could be found" or some customizable message?

Thank you,

have problem with set default value when options feed from AJAX

please help
var options = this.state.LGs
? this.state.LGs.map(function(LG) {
return {
name: LG.StructName,
value: LG.StructID
};
})
: [];

<SelectSearch
        name="LG"
        value={this.state.LG}
        options={options}
        placeholder="Select LG"
      />

I could not set default value.
the error show:

TypeError: this.state is undefined[Learn More] index.js:400
findByValue 25

if (!source || source.length < 1) {
--> findSource = this.state.defaultOptions;
}

Problem with search

Hi, in your documentation you said:
/**

  • The options array should contain objects.
  • Required keys are "name" and "value" but you can have and use any number of key/value pairs.
    */
    So I added new key value pair to the option object (address: "hello@something")
    And I render my options like this (attached screenshot) name, address and image
    image
    The question is how can I search by address because now it search only in name values

Searching large data.

I have an Select with about 2,900 names. The search is not refined.
image
image
If I backspace the search also gets really confused and messes up.

Dropdown is not flexible

Hi Team,
having issue with dropdown -> Onclick dropdown list open after based on the screen it has to adjust but its always dropdown list will open down side only can any one help me

default value does not set properly.

A really cool project, love it. does exactly what I need.

Might find a defect, my test case: first init with empty value/options, then pass in valid value/options, after re-render, default value would not show properly.

Potential fix as following marked part, should use options from newly passed in props check if new value is valid.

Ning.

componentWillReceiveProps(nextProps) {
const nextState = {};
const { defaultOptions, value } = this.state;

    if (nextProps.options !== defaultOptions) {
        const flattenedOptions = FlattenOptions(nextProps.options);

        nextState.options = flattenedOptions;
        nextState.defaultOptions = flattenedOptions;
    }

     if (nextProps.value !== value) {

const option = this.findByValue(nextState.defaultOptions, nextProps.value);

        if (option) {
            nextState.value = nextProps.value;
            nextState.search = option.name;
        } else {
            nextState.value = [];
            nextState.search = '';
        }
    }

    this.setState(nextState);
}

IE<10 compatibility

Console Error:
Unable to get property 'multiple' of undefined or null reference

Test v1

A new version under the next branch (and react-select-search@next on npm) is ready for test and will be the new v1. It contains major refactoring and API changes, so migration guide is still left to write. This is also a good place to discuss design decisions.

Keyboard question

When I type in a value in the search list on the demo page, should I be able to use the down arrow key to get to various items? For instance, on the country one, if I type "Fr", I would expect to be able to hit the down arrow key and get to French Guiana. Right now, the only way I see to select it is typing enough that it is the first item on the list or using the mouse.

Thanks!

State change update fails to change text

We experienced an issue where changing the state value, that the value prop pointed at, to a blank string would change most aspects of the object, however the search input would not clear until a manual click was performed outside of the element. Triggering a click via any other means would not cause a refresh, nor would any changes to the element via jquery or javascript.

The only thing that ended up working was by getting a ref to the index object, and calling the __outsideClickHandler manually after changing the value. On our end we're also running a force update after this, and this is in the callback of the setState that clears the value.

While I've solved the issue on my end, this really doesn't seem like intended behavior, and someone else will likely have this issue.

Uncaught TypeError: _react.default.createRef is not a function

Nice component, but when I tried to use it in my project (react 16.2 version) I've got error

Uncaught TypeError: _react.default.createRef is not a function at new SelectSearch (index.js?cd67:180) at new SelectSearch (eval at <anonymous> (utils.js?0184:112), <anonymous>:5:7) at constructClassInstance (react-dom.development.js?cada:6355) at updateClassComponent (react-dom.development.js?cada:7839) at beginWork (react-dom.development.js?cada:8225) at performUnitOfWork (react-dom.development.js?cada:10224) at workLoop (react-dom.development.js?cada:10288) at HTMLUnknownElement.callCallback (react-dom.development.js?cada:542) at Object.invokeGuardedCallbackDev (react-dom.development.js?cada:581) at invokeGuardedCallback (react-dom.development.js?cada:438)

A way to set a maximum display value for search boxes.

Currently I have a list of 800 items I wish to be able to fuzzy search. The issue arises that this of course is very slow to render and makes it generally sluggish.

I was wondering if there was a way to set a maximum amount of items to render at once. Of course this will mean a user will have to start typing first to filter through the results but it should mean it renders faster.

Thanks

Wrong selection when option's value is zero

Selecting an option with zero as value triggers the selection of the first option(index 0) e.g

const options = [
    { name: '100%', value: 100 },
    { name: '50%', value: 50 },
    { name: 'None', value: 0}
]

<SelectSearch
     name="rate"
     options={options}
 />

I'm assuming there's truthy check for null values in the code that gets tripped when it encounters a zero.

How to change state value by entry?

How can you write create a typical react input workflow with react-select-search? onChange is only fired on selection, not keypress so I cant access a state/update state stored value and have to use jquery to select the value if on non selected values.

Allow virtualized options

Great component, unfortunately I cannot use it with the size of the list I have. If the options could be virtualized, it would be perfect.

Keep getting error on select

The issue start to occured from 10.1 version. message is:
Uncaught TypeError: this.state.value.slice is not a function
My code is below:

changeUser = option => {
    this.setState({
      userId: option.value
    });
  };

<SelectSearch
                          name="userId"
                          className="select-search-box"
                          value={defaultFormData.userId}
                          height={172}
                          onChange={value => this.changeUser(value)}
                          options={ userOptions }
                          placeholder={translate('main.projectList.user')}
                        />

I roll bact to 9.6 version it is fixed.

Keyboard usability issues

When I use the keyboard to select an option (e.g. ArrowDown - ArrowDown - ArrowDown - Enter), the field is blurred. So then when I push tab to get to the next field, nothing is focused, so it focuses on the first field in the page instead of the next field in the page.

image

I think the best behavior would be to keep the search field focused, select() the text, and close the options dropdown. This allows the user to see what they selected and tab to the next field. They could also start typing a fresh search immediately, which would overwrite the selected text. Ideally they could also use the arrow keys to browse the options (which would redisplay the options).

I can accomplish a behavior that's pretty close using the valueChanged callback like this:

        // Need to set the search field value because otherwise it is cleared when the value changes.
        this.selectSearch.refs.search.value = getSelectedOptionDisplayName();
        this.selectSearch.refs.search.select();
        // Trick the SelectSearch into acting like it was blurred.
        this.selectSearch.onBlur();
        var $input = $(ReactDOM.findDOMNode(this.selectSearch.refs.search));
        // If it's the tab key, return true to let the event continue. Otherwise trick the selectSearch to act like it was focused.
        $input.one('keydown', (event) => (event.which == 9 ? true : this.selectSearch.onFocus()));

Which gives this behavior:

image

What do you think? Should this be the built-in behavior? How could I accomplish this in a less hacky way?

Not Rendering Correctly

It is rendering all the options as pure text and displaying them even when the input isn't selected.
Something isn't right.
image

You can see the problem in this small example project:
Edit A Simple React Router v4 Tutorial

How use `id` filed as option value ?

Hello everyone.
In my case I have a list of objects like that:
[{ id: 1, first_name: 'anyname'} , ... ]

I have

<SelectSearch name="userId" className="select-search-box" // multiple value={0} height={172} customEntries={true} fuse={defaultFormData.userSearchObj} options={ users.length ? users : [{ id: 0, first_name: '' }] } renderOption={option => option ? ${option.first_name}} renderValues={option => option.id } />

but when I select one item all items became selected. How can I fix this situation ?

Cannot change the options list after the component has been rendered

Currently attempting to modify the options prop with my list in however it does not seem to work. I am loading the list dynamically and as such the option list can change. Is there any way of working around this?

If its by design then can I suggest you rename the options property to initialOptions or defaultOptions (which I believe react ask you to do if it sets the value once and does not update after that)?

PropTypes not working properly

I have forgottent to specify options.

Expected:

propTypes would say that options are required.

Actual:

   FlattenOptions.js:10 Uncaught TypeError: Cannot read property 'forEach' of undefined

Comparison with react-select

Hi, I was looking for a React select component, and found this library. Thanks for publishing it!

Would you be able to compare it with some of the other React select libraries? How would a developer choose between it, and react-select for example?

clear input

hey man,
i'm trying to think of a clever way to clear the input onclick (button). Any thoughts on the best way to approach this?

Getting the value of the input

Please excuse my ignorance if it's right in front of my face... vary new to react here!

After i've selected one of the options from the array, how do I access that value?

Any guidance much appreciated!

(in my case i'd like to update my state/redux store with the input value)

Got error when using number as value

I got this error when using number as value

Uncaught TypeError: this.state.value.slice is not a function
    at SelectSearch.chooseOption (index.js:509)
    at onClick (index.js:670)

I think this line cause the error

var currentValue = this.state.value.slice();

Hope that you can update it! Thank you so much!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.