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_page between 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