2

I am using the react-autocomplete npm package to build the autocomplete functionality in my Reactjs app. So far I have been able to render dropdown items that match the user's input, as you see in the documentation of this package. However, I would like to generate a default text in the dropdown as No results found whenever user's input do not match any of the dropdown items. And to be honest I am really struggling with it.

I tried adding custom function to the shouldItemRender to change the state and dropdown items accordingly but it does not help either. Here is the snippet of my code -


const suggestions=  [{id: 100 , text:  "Aluminium extracts" }, {id: 101 , text:  "Copper extracts" }] 

<Autocomplete
    getItemValue={(item) => item.text}
    items={ suggestions }
    renderItem={(item, isHighlighted) => {
            return <div> {item.text} </div>)
        }
    }
    shouldItemRender={(item, value) => item.text.toLowerCase().indexOf(value.toLowerCase()) > -1}
    // shouldItemRender={(item, value) => handleRender(item, value) }
    value={value}
    onChange={(e, newValue) => { setValue(e.target.value) }}
    onSelect={(v) => handleInput(v)}
    inputProps={{ placeholder: "start typing"}}
/>

I will appreciate your help if you can help me accomplish this. Thank you.

relu
  • 333
  • 1
  • 3
  • 18
  • Does this help? [Custom Menu Example](https://github.com/reactjs/react-autocomplete/blob/master/examples/custom-menu/app.js#L52,L62) – vighnesh153 Oct 03 '22 at 15:20
  • I tried conditional rendering of `items` using `renderMenu` as shown in the example above but it does not help, it breaks everything :( – relu Oct 03 '22 at 15:53
  • Could you please create a minimal reproducible stackblitz link? – vighnesh153 Oct 04 '22 at 03:21

4 Answers4

1

Use renderMenu to check whether a match found or not. If there is no match found then show the No match found, if match found then return the items and renderItem will render the items list.

<ReactAutocomplete
  items={[
    { id: "foo", label: "foo" },
    { id: "bar", label: "bar" },
    { id: "baz", label: "baz" },
  ]}
  shouldItemRender={(item, value) =>
    item.label.toLowerCase().indexOf(value.toLowerCase()) > -1
  }
  getItemValue={(item) => item.label}
  renderItem={(item, highlighted) => (
    <div
      key={item.id}
      style={{ backgroundColor: highlighted ? "#eee" : "transparent" }}
    >
      {item.label}
    </div>
  )}
  renderMenu={(items, value) => (
    <div>{items.length === 0 ? `No matches for ${value}` : items}</div>
  )}
  value={this.state.value}
  onChange={(e) => this.setState({ value: e.target.value })}
  onSelect={(value) => this.setState({ value })}
/>

Check this link for better understanding. https://github.com/reactjs/react-autocomplete/blob/master/examples/custom-menu/app.js

S N Sharma
  • 1,436
  • 2
  • 7
  • 20
0

The best way to provide message for the case where there are no options is to use renderMenu prop to override the result of dropdown content when no items found to matching search criteria.

import { useState } from "react";

const suggestions = [
  { id: 100, text: "Aluminium extracts" },
  { id: 101, text: "Copper extracts" }
];

export default function App() {
  const [searchTerm, setSearchTerm] = useState("");
  const items = suggestions.filter((item) =>
    item.text.toLowerCase().includes(searchTerm.toLowerCase())
  );
  return (
    <div className="App">
      <Autocomplete
        getItemValue={(item) => item.text}
        renderMenu={(items) =>
          items.length > 0 ? <div children={items} /> : <div>No results found</div>
        }
        items={items}
        renderItem={(item, isHighlighted) => {
          return <div> {item.text} </div>;
        }}
        value={searchTerm}
        onChange={(e, newValue) => {
          setSearchTerm(e.target.value);
        }}
        onSelect={(text) => setSearchTerm(text)}
        inputProps={{ placeholder: "start typing" }}
      />
    </div>
  );
}
0

Please make it simple & Use renderMenu instead of renderItem for Component rendering.

1harshh
  • 31
  • 7
-1

Have you tried this?

items={ suggestions.lenght ? suggestions : [{id: -1, text: "No results found" }] }
isItemSelectable=(item)=>item.id !== -1
Sylvain
  • 509
  • 1
  • 7
  • 17