Pagination
Automatic infinite scroll to progressively load large datasets. When you scroll the results list to the end, Vanilla Smart Select automatically detects and loads the next page.
GitHub Repositories - Infinite Scroll
Search GitHub repositories with automatic infinite scroll. Scroll to the bottom to load more results.
View code
HTML
<select id="github-repos"></select>
JavaScript
const reposSelect = new VanillaSmartSelect('#github-repos', {
placeholder: 'Type to search repositories...',
allowClear: true,
ajax: {
url: 'https://api.github.com/search/repositories',
delay: 400,
data: (params) => ({
q: params.term || 'javascript',
page: params.page || 1,
per_page: 10
}),
processResults: (data, params) => {
const results = data.items.map(repo => ({
id: repo.id,
text: repo.full_name,
name: repo.name,
full_name: repo.full_name,
description: repo.description || 'No description',
stars: repo.stargazers_count,
forks: repo.forks_count,
language: repo.language || 'Unknown',
url: repo.html_url
}));
return {
results: results,
pagination: {
more: data.items.length >= 10
}
};
}
},
templateResult: (item) => {
const div = document.createElement('div');
div.innerHTML = `
<div style="display: flex; gap: 12px;">
<div>📦</div>
<div>
<div style="font-weight: 500;">${item.full_name}</div>
<div style="font-size: 12px; color: #666;">${item.description}</div>
<div style="font-size: 11px; color: #888; margin-top: 4px;">
⭐ ${item.stars.toLocaleString()} | 🍴 ${item.forks.toLocaleString()} | 💻 ${item.language}
</div>
</div>
</div>
`;
return div;
},
templateSelection: (item) => {
return `📦 ${item.full_name}`;
}
});
GitHub Users - Infinite Scroll
Search GitHub users with automatic pagination.
View code
HTML
<select id="github-users"></select>
JavaScript
const usersSelect = new VanillaSmartSelect('#github-users', {
placeholder: 'Type to search users...',
allowClear: true,
ajax: {
url: 'https://api.github.com/search/users',
delay: 400,
data: (params) => ({
q: params.term || 'john',
page: params.page || 1,
per_page: 15
}),
processResults: (data) => {
const results = data.items.map(user => ({
id: user.id,
text: user.login,
login: user.login,
avatar: user.avatar_url,
url: user.html_url,
type: user.type
}));
return {
results: results,
pagination: {
more: data.items.length >= 15
}
};
}
},
templateResult: (item) => {
const div = document.createElement('div');
div.style.display = 'flex';
div.style.alignItems = 'center';
div.style.gap = '10px';
div.innerHTML = `
<img src="${item.avatar}" style="width: 32px; height: 32px; border-radius: 50%;" />
<div>
<div style="font-weight: 500;">${item.login}</div>
<div style="font-size: 11px; color: #666;">${item.type}</div>
</div>
`;
return div;
},
templateSelection: (item) => {
return item.login;
}
});
Simulated Paginated API
Simulated example with local data to demonstrate the pagination concept (100 items).
View code
HTML
<select id="simulated"></select>
JavaScript
// Generate 100 example items
const allItems = Array.from({ length: 100 }, (_, i) => ({
id: i + 1,
text: `Item ${i + 1}`,
category: ['Electronics', 'Books', 'Clothing', 'Food'][i % 4],
price: (Math.random() * 1000).toFixed(2)
}));
const simulatedSelect = new VanillaSmartSelect('#simulated', {
placeholder: 'Search items (simulated)...',
allowClear: true,
ajax: {
url: '', // Não usado
delay: 300,
transport: (params) => {
// Simulate API delay
return new Promise((resolve) => {
setTimeout(() => {
const term = (params.term || '').toLowerCase();
const page = params.page || 1;
const perPage = 10;
// Filter by search term
let filtered = allItems.filter(item =>
item.text.toLowerCase().includes(term) ||
item.category.toLowerCase().includes(term)
);
// Paginate
const start = (page - 1) * perPage;
const end = start + perPage;
const pageItems = filtered.slice(start, end);
resolve({
items: pageItems,
total: filtered.length
});
}, 500);
});
},
processResults: (data, params) => {
const page = params.page || 1;
const perPage = 10;
const hasMore = (page * perPage) < data.total;
return {
results: data.items,
pagination: { more: hasMore }
};
}
},
templateResult: (item) => {
const div = document.createElement('div');
div.innerHTML = `
<div style="display: flex; justify-content: space-between;">
<div>
<div style="font-weight: 500;">${item.text}</div>
<div style="font-size: 11px; color: #666;">${item.category}</div>
</div>
<div style="color: #007bff; font-weight: 600;">$${item.price}</div>
</div>
`;
return div;
},
templateSelection: (item) => {
return `${item.text} - $${item.price}`;
}
});
Pagination Configuration
processResults Structure
To enable pagination, processResults must return an object with the pagination property:
processResults: (data, params) => {
return {
results: [...], // Results array
pagination: {
more: true // true if there are more pages
}
};
}
Automatic Parameters
Vanilla Smart Select automatically passes the page number in params.page:
data: (params) => ({
q: params.term,
page: params.page || 1, // Current page
per_page: 10
})
Pagination Events
| Event | Description |
|---|---|
vs:ajaxLoading |
Fired when a page is being loaded |
vs:ajaxSuccess |
Fired when the page is successfully loaded |
vs:ajaxError |
Fired if there is an error loading |
select.addEventListener('vs:ajaxLoading', (e) => {
console.log('Loading page:', e.detail.params.page);
});
select.addEventListener('vs:ajaxSuccess', (e) => {
console.log('Loaded', e.detail.results.results.length, 'items');
console.log('Has more?', e.detail.results.pagination.more);
});
✅ Usage Tips
- Use
per_pagebetween 10-20 for better performance - Infinite scroll is automatic - no additional code needed
- Results are accumulated automatically
- Works perfectly with search - each term resets pagination
- Combine with custom templates for rich results