Now.js Framework Documentation
Autocomplete
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 termlimit- 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
Product Search
<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' }, ...]Related Documentation
- TextElementFactory - Text inputs with autocomplete
- FormManager - Form handling