Now.js Framework Documentation

Now.js Framework Documentation

Autocomplete

EN 15 Dec 2025 06:48

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' }, ...]