Now.js Framework Documentation

Now.js Framework Documentation

Autocomplete

EN 04 Sep 2026 01:40

Autocomplete

Overview

Autocomplete is a component for input autocomplete in Now.js Framework. It supports both datalist and AJAX suggestions.

When to use:

  • Need autocomplete suggestions
  • Need search suggestions from API
  • Need typeahead functionality
  • Need to filter from datalist

Why use it:

  • ✅ Keyboard navigation (Arrow keys, Enter, Escape)
  • ✅ AJAX support
  • ✅ Datalist filtering
  • ✅ Debounced input
  • ✅ Customizable appearance
  • ✅ Loading state

Basic Usage

With Static Datalist

<input type="text" id="city" list="cities">
<datalist id="cities">
  <option value="Bangkok">Bangkok</option>
  <option value="Chiang Mai">Chiang Mai</option>
  <option value="Phuket">Phuket</option>
  <option value="Pattaya">Pattaya</option>
</datalist>

<script>
const instance = Autocomplete.create(document.getElementById('city'));
</script>

With AJAX URL

<input type="text" id="search" placeholder="Search...">

<script>
const instance = Autocomplete.create(document.getElementById('search'), {
  url: '/api/search',
  minLength: 2,
  delay: 300,
  limit: 10
});
</script>

Configuration

Autocomplete.create(element, {
  // Minimum characters before searching
  minLength: 2,

  // Debounce delay (ms)
  delay: 300,

  // Maximum suggestions
  limit: 10,

  // API URL for AJAX
  url: '/api/search',

  // CSS classes
  listClass: 'autocomplete-list',
  activeClass: 'active',
  loadingClass: 'loading'
});

AJAX Response Format

API should return array of objects or strings:

// Objects with value and label
[
  { value: 'th', label: 'Thailand' },
  { value: 'jp', label: 'Japan' },
  { value: 'us', label: 'United States' }
]

// Or simple strings
['Apple', 'Banana', 'Cherry']

Query parameters sent:

  • q - search term
  • limit - maximum results

API Reference

Autocomplete.create(element, options)

Create autocomplete instance

Parameter Type Description
element HTMLInputElement Input element
options.url string API URL for AJAX
options.minLength number Minimum characters (default: 2)
options.delay number Debounce delay ms (default: 300)
options.limit number Maximum suggestions
options.listClass string CSS class for list
options.activeClass string CSS class for active item
options.loadingClass string CSS class for loading

Returns: Object - Instance

Autocomplete.destroy(instance)

Destroy instance

Parameter Type Description
instance Object Instance from create()

Keyboard Navigation

Key Action
↓ Select next item
↑ Select previous item
Enter Select current item
Escape Close suggestions

Events

When an item is selected, a change event is dispatched:

input.addEventListener('change', (e) => {
  console.log('Selected:', e.target.value);
});

CSS Styling

/* Suggestion list */
.autocomplete-list {
  position: absolute;
  width: 100%;
  max-height: 200px;
  overflow-y: auto;
  background: white;
  border: 1px solid #ddd;
  border-radius: 4px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
  list-style: none;
  margin: 0;
  padding: 0;
  z-index: 1000;
}

.autocomplete-list li {
  padding: 8px 12px;
  cursor: pointer;
}

.autocomplete-list li:hover,
.autocomplete-list li.active {
  background: #f0f0f0;
}

/* Loading state */
input.loading {
  background-image: url('/images/spinner.gif');
  background-repeat: no-repeat;
  background-position: right 8px center;
}

Real-World Examples

<div class="search-container">
  <input type="text" id="product-search" placeholder="Search products...">
</div>

<script>
const searchInput = document.getElementById('product-search');
const autocomplete = Autocomplete.create(searchInput, {
  url: '/api/products/search',
  minLength: 2,
  delay: 300,
  limit: 8
});

searchInput.addEventListener('change', async (e) => {
  const productId = e.target.value;
  // Navigate to product page
  window.location.href = `/products/${productId}`;
});
</script>

User Mention

<textarea id="comment" placeholder="Type @ to mention a user"></textarea>

<script>
// Custom trigger on @
const textarea = document.getElementById('comment');
let mentionStart = -1;

textarea.addEventListener('input', async (e) => {
  const value = e.target.value;
  const cursorPos = e.target.selectionStart;

  // Check for @ trigger
  const lastAt = value.lastIndexOf('@', cursorPos);
  if (lastAt >= 0) {
    const query = value.substring(lastAt + 1, cursorPos);
    if (query.length >= 2) {
      // Use Autocomplete API
      const users = await fetch(`/api/users/search?q=${query}`);
      // Show suggestions...
    }
  }
});
</script>

Common Pitfalls

⚠️ 1. Parent Position

/* ❌ If parent has no position - list won't align */
.container {
  /* no position */
}

/* ✅ Must have position relative */
.container {
  position: relative;
}

⚠️ 2. API Response Format

// ❌ Incorrect response format
{ success: true, products: [...] }

// ✅ Return array directly
[{ value: '1', label: 'Product 1' }, ...]