pstanoev / simple-svelte-autocomplete

Simple Autocomplete / typeahead component for Svelte
http://simple-svelte-autocomplete.surge.sh/
MIT License
464 stars 78 forks source link
autocomplete svelte svelte-component svelte-components svelte-v3 typeahead

Simple Svelte Autocomplete

Autocomplete / Select / Typeahead component made with Svelte

Live demo http://simple-svelte-autocomplete.surge.sh/

Install

npm i -D simple-svelte-autocomplete

Usage

Import the component and define items:

import AutoComplete from "simple-svelte-autocomplete"

const colors = ["White", "Red", "Yellow", "Green", "Blue", "Black"]
let selectedColor

And use it like this:

<AutoComplete items="{colors}" bind:selectedItem="{selectedColor}" />

You can also use it with array of objects:

const colorList = [
  { id: 1, name: "White", code: "#FFFFFF" },
  { id: 2, name: "Red", code: "#FF0000" },
  { id: 3, name: "Yellow", code: "#FF00FF" },
  { id: 4, name: "Green", code: "#00FF00" },
  { id: 5, name: "Blue", code: "#0000FF" },
  { id: 6, name: "Black", code: "#000000" },
]

let selectedColorObject

Just define which field should be used as label:

<AutoComplete items="{colorList}" bind:selectedItem="{selectedColorObject}" labelFieldName="name" />

Specifying function for label instead of field name is also supported:

<AutoComplete items={colorList} bind:selectedItem={selectedColorObject} labelFunction={color =>
color.id + '. ' + color.name} />

By default the component searches by the item label, but it can also search by custom fields by specifying keywords function. For example to enable searching by color name and color HEX code:

<AutoComplete items={colorList} bind:selectedItem={selectedColorObject} labelFieldName="name"
keywordsFunction={color => color.name + ' ' + color.code} />

Asynchronous loading of items

Define a searchFunction which will be called with keyword and maxItemsToShowInList parameters. If you have searchFunction defined you don't need to specify items since the function will be used for loading. The delay parameter specifies the time to wait between user input and calling the searchFunction. It is recommend that delay > 200ms is set when using a remote search function to avoid sending too many requests. The localFiltering parameter can be set to false if the search function already returns filtered items according to the user input.

<AutoComplete
  searchFunction="{getItems}"
  delay="200"
  localFiltering={false}
  labelFieldName="name"
  valueFieldName="id"
  bind:selectedItem="{myValue}"
/>
async function getItems(keyword) {
  const url = "/api/my-items/?format=json&name=" + encodeURIComponent(keyword)

  const response = await fetch(url)
  const json = await response.json()

  return json.results
}
{
  "results": [
    {
      "id": 1,
      "name": "Sample One",
      "date": "2020-09-25"
    },
    {
      "id": 2,
      "name": "Sample Two",
      "date": "2020-09-26"
    }
  ]
}

Properties

Behaviour

Events

UI options

CSS classes and IDs

UI Slots

<div slot="item" let:item let:label>
  {@html label}
  <!-- to render the default higliglighted item label -->
  <!-- render anything else -->
  <span style="color:{item.propertyX}">{item.propertyY}</span>
</div>
<div slot="no-results" let:noResultsText>
    <span>{noResultsText}</span>
</div>

The noResultsText variable is optional and can be ommited.

<div slot="loading" let:loadingText>
    <span>{loadingText}</strong>
</div>
<div slot="tag">
  <span class="tag">{label}</span>
  <span class="delete-tag" on:click|preventDefault="{unselectItem(item)}"></span>
</slot>
<div slot="menu-header" let:nbItems let:maxItemsToShowInList>
  <div class="dropdown-item">Choose between those {nbItems} items</div>
  <hr class="dropdown-divider">
</div>
<div slot="dropdown-footer" let:nbItems  let:maxItemsToShowInList>
    ...
</div>

CSS properties

Note: Setting noInputStyles=true will disable the use of the autocomplete-input class above.

Use global to apply styles, example:

  .parent :global(.childClass) {
    color: red;
  }

The component is inteded to use with Bulma but it can be adapted to use Boostrap or anything else.