JSPM

  • Created
  • Published
  • Downloads 305765
  • Score
    100M100P100Q216940F
  • License MIT

WAI-ARIA compliant React autosuggest component

Package Exports

  • react-autosuggest

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (react-autosuggest) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

Build Status Coverage Status bitHound Overall Score Issues stats Pull Requests stats NPM Downloads NPM Version

React Autosuggest

WAI-ARIA compliant autosuggest component built in React

Demo

Check out the Homepage and the Codepen examples.

Features

Installation

npm install react-autosuggest --save

Basic Usage

import Autosuggest from 'react-autosuggest';

const languages = [
  {
    name: 'C',
    year: 1972
  },
  {
    name: 'Elm',
    year: 2012
  },
  ...
];

function getSuggestions(value) {
  const inputValue = value.trim().toLowerCase();
  const inputLength = inputValue.length;

  return inputLength === 0 ? [] : languages.filter(lang =>
    lang.name.toLowerCase().slice(0, inputLength) === inputValue
  );
}

function getSuggestionValue(suggestion) { // when suggestion is selected, this function tells
  return suggestion.name;                 // what should be the value of the input
}

function renderSuggestion(suggestion) {
  return (
    <span>{suggestion.name}</span>
  );
}

class Example extends React.Component {
  constructor() {
    super();

    this.state = {
      value: '',
      suggestions: []
    };
  }

  onChange = (event, { newValue }) => {
    this.setState({
      value: newValue
    });
  };

  onSuggestionsFetchRequested = ({ value }) => {
    this.setState({
      suggestions: getSuggestions(value)
    });
  };

  onSuggestionsClearRequested = () => {
    this.setState({
      suggestions: []
    });
  };

  render() {
    const { value, suggestions } = this.state;
    const inputProps = {
      placeholder: 'Type a programming language',
      value,
      onChange: this.onChange
    };

    return (
      <Autosuggest
        suggestions={suggestions}
        onSuggestionsUpdateRequested={this.onSuggestionsUpdateRequested}
        onSuggestionsClearRequested={this.onSuggestionsClearRequested}
        getSuggestionValue={getSuggestionValue}
        renderSuggestion={renderSuggestion}
        inputProps={inputProps} />
    );
  }
}

Props

suggestions (required)

Array of suggestions to display. The only requirement is that suggestions is an array. Items in this array can take an arbitrary shape.

For a plain list of suggestions, every item in suggestions should be a single suggestion. It's up to you what shape every suggestion takes. For example:

const suggestions = [
  {
    text: 'Apple'
  },
  {
    text: 'Banana'
  },
  {
    text: 'Cherry'
  },
  {
    text: 'Grapefruit'
  },
  {
    text: 'Lemon'
  }
];

To display multiple sections, every item in suggestions should be a single section. Again, it's up to you what shape every section takes. For example:

const suggestions = [
  {
    title: 'A',
    suggestions: [
      {
        id: '100',
        text: 'Apple'
      },
      {
        id: '101',
        text: 'Apricot'
      }
    ]
  },
  {
    title: 'B',
    suggestions: [
      {
        id: '102',
        text: 'Banana'
      }
    ]
  },
  {
    title: 'C',
    suggestions: [
      {
        id: '103',
        text: 'Cherry'
      }
    ]
  }
];

onSuggestionsFetchRequested (required)

This function will be called every time you need to update suggestions. It has the following signature:

function onSuggestionsFetchRequested({ value })

where value is current value of the input.

onSuggestionsClearRequested (required unless alwaysRenderSuggestions={true})

This function will be called every time you need to clear suggestions.

All you have to do in this function is to set suggestions to an empty array.

getSuggestionValue (required)

When user navigates the suggestions using the Up and Down keys, the input should display the highlighted suggestion. You design how suggestion is modelled. Therefore, it's your responsibility to tell Autosuggest how to map suggestions to input values.

This function gets the suggestion in question, and it should return a string. For example:

function getSuggestionValue(suggestion) {
  return suggestion.text;
}

renderSuggestion (required)

Use your imagination to define how suggestions are rendered.

The signature is:

function renderSuggestion(suggestion, { query })

where:

  • suggestion - The suggestion to render
  • query - Used to highlight the matching string. As user types in the input field, query will be equal to the trimmed value of the input. Then, if user interacts using the Up or Down keys, the input will get the value of the highlighted suggestion, but query will remain to be equal to the trimmed value of the input prior to the Up and Down interactions.

It should return a string or a ReactElement. For example:

function renderSuggestion(suggestion) {
  return (
    <span>{suggestion.text}</span>
  );
}

Important: renderSuggestion must be a pure function (we optimize rendering performance based on this assumption).

renderSuggestionsContainer (optional)

You shouldn't use this function unless you want to customize the behaviour of the suggestions container. For example, you might want to add a custom text before/after the suggestions list, or customize the scrolling behaviour of the suggestions container.

The signature is:

function renderSuggestionsContainer(props)

You should pass all the props to the topmost element that is returned from renderSuggestionsContainer with the following exceptions:

  • children - these are the suggestions themselves. It's up to you where to render them.
  • ref - when renderSuggestionsContainer returns a composite component (e.g. <IsolatedScroll ... /> as opposed to a DOM node like <div ... />), you should call ref with the topmost element that the composite component renders.

Examples:

function renderSuggestionsContainer({ children, ...rest }) {
  return (
    <div {...rest}>
      <p>
        Some text
      </p>
      {children}
    </div>
  );
}
import IsolatedScroll from 'react-isolated-scroll';

function renderSuggestionsContainer({ ref, ...rest }) {
  const callRef = isolatedScroll => {
    if (isolatedScroll !== null) {
      ref(isolatedScroll.component);
    }
  };

  return (
    <IsolatedScroll {...rest} ref={callRef} />
  );
}

inputProps (required)

Autosuggest is a controlled component. Therefore, you should pass at least a value and an onChange callback to the input field. You can pass any other props as well. For example:

const inputProps = {
  value,          // usually comes from the application state
  onChange,       // called every time input value changes
  onBlur,         // called when input loses focus, e.g. when user presses Tab
  type: 'search',
  placeholder: 'Enter city or postcode'
};

inputProps.onChange (required)

The signature is:

function onChange(event, { newValue, method })

where:

  • newValue - the new value of the input field
  • method - string describing how the change has occurred. The possible values are:
    • 'down' - user pressed Down
    • 'up' - user pressed Up
    • 'escape' - user pressed Escape
    • 'enter' - user pressed Enter
    • 'click' - user clicked (or tapped) on suggestion
    • 'type' - none of the methods above (usually means that user typed something, but can also be that they pressed Backspace, pasted something into the field, etc.)

inputProps.onBlur (optional)

The signature is:

function onBlur(event, { focusedSuggestion })

where:

  • focusedSuggestion - the suggestion that was highlighted just before the input lost focus, or null if there was no highlighted suggestion.

shouldRenderSuggestions (optional)

By default, suggestions are rendered when input field isn't blank. Feel free to override this behaviour.

This function gets the current value of the input, and it should return a boolean.

For example, to display suggestions only when input is at least 3 characters long, do:

function shouldRenderSuggestions(value) {
  return value.trim().length > 2;
}

When shouldRenderSuggestions returns true, suggestions will be rendered only when the input field is focused.

If you would like to render suggestions regardless of whether the input field is focused or not, set alwaysRenderSuggestions={true} (shouldRenderSuggestions is ignored in this case).

alwaysRenderSuggestions (optional)

Set alwaysRenderSuggestions={true} if you'd like to always render the suggestions.

Important: Make sure to set the initial value of suggestions to match the initial value of inputProps.value.

multiSection (optional)

By default, Autosuggest renders a plain list of suggestions.

If you'd like to have multiple sections (with optional titles), set multiSection={true}.

renderSectionTitle (required when multiSection={true})

When rendering multiple sections, you need to tell Autosuggest how to render a section title.

This function gets the section to render (an item in the suggestions array), and it should return a string or a ReactElement. For example:

function renderSectionTitle(section) {
  return (
    <strong>{section.title}</strong>
  );
}

If renderSectionTitle returns null or undefined, section title is not rendered.

getSectionSuggestions (required when multiSection={true})

When rendering multiple sections, you need to tell Autosuggest where to find the suggestions for a given section.

This function gets the section to render (an item in the suggestions array), and it should return an array of suggestions to render in the given section. For example:

function getSectionSuggestions(section) {
  return section.suggestions;
}

Note: Sections with no suggestions are not rendered.

onSuggestionSelected (optional)

This function is called when suggestion is selected. It has the following signature:

function onSuggestionSelected(event, { suggestion, suggestionValue, sectionIndex, method })

where:

  • suggestion - the selected suggestion
  • suggestionValue - the value of the selected suggestion (equivalent to getSuggestionValue(suggestion))
  • sectionIndex - when rendering multiple sections, this will be the section index (in suggestions) of the selected suggestion. Otherwise, it will be null.
  • method - string describing how user selected the suggestion. The possible values are:
    • 'click' - user clicked (or tapped) on the suggestion
    • 'enter' - user selected the suggestion using Enter

focusInputOnSuggestionClick (optional)

By default, focusInputOnSuggestionClick={true}, which means that, every time suggestion is clicked (or tapped), the input field keeps the focus.

On mobile devices, when input is focused the native keyboard appears. You'll probably want to lose the focus when suggestion is tapped in order to hide the keyboard.

You can do something like this:

<Autosuggest focusInputOnSuggestionClick={!isMobile} ... />

where isMobile is a boolean describing whether Autosuggest operates on a mobile device or not. You can use kaimallea/isMobile, for example, to determine that.

focusFirstSuggestion (optional)

When focusFirstSuggestion={true}, Autosuggest will automatically highlight the first suggestion. Defaults to false.

theme (optional)

Autosuggest comes with no styles.

It uses react-themeable to allow you to style your Autosuggest component using CSS Modules, Radium, React Style, JSS, Inline styles, or even global CSS.

For example, to style the Autosuggest using CSS Modules, do:

/* theme.css */

.container { ... }
.input { ... }
.suggestionsContainer { ... }
.suggestion { ... }
.suggestionFocused { ... }
...
import theme from 'theme.css';
<Autosuggest theme={theme} ... />

When not specified, theme defaults to:

{
  container:            'react-autosuggest__container',
  containerOpen:        'react-autosuggest__container--open',
  input:                'react-autosuggest__input',
  suggestionsContainer: 'react-autosuggest__suggestions-container',
  suggestionsList:      'react-autosuggest__suggestions-list',
  suggestion:           'react-autosuggest__suggestion',
  suggestionFocused:    'react-autosuggest__suggestion--focused',
  sectionContainer:     'react-autosuggest__section-container',
  sectionTitle:         'react-autosuggest__section-title'
}

The following picture illustrates how theme keys correspond to Autosuggest DOM structure:

DOM structure

id (required when multiple Autosuggest components are rendered on a page)

The only reason id exists, is to set ARIA attributes (they require a unique id).

When rendering a single Autosuggest, don't set the id (it will be set to '1', by default).

When rendering multiple Autosuggest components on a page, make sure to give them unique ids. For example:

<Autosuggest id="source" ... />
<Autosuggest id="destination" ... />

Development

npm install
npm start

Now, open http://localhost:3000/demo/dist/index.html and start hacking!

License

MIT