Interactive Features and APIs
Build dynamic web features with AI — fetch data from APIs, create search and filter interfaces, implement infinite scroll, and handle loading states gracefully.
Premium Course Content
This lesson is part of a premium course. Upgrade to Pro to unlock all premium courses and content.
- Access all premium courses
- 1000+ AI skill templates included
- New content added weekly
🔄 Quick Recall: In the last lesson, you added interactivity with vanilla JavaScript — DOM manipulation, event handling, and form validation. Now let’s connect to external data sources and build truly dynamic features.
Fetching Data from APIs
Basic API Call Pattern
Write vanilla JavaScript to fetch data from a REST API:
API endpoint: [URL or describe the API]
Expected response format: JSON array of objects with [describe fields]
Requirements:
- Use async/await with fetch()
- Show a loading indicator while fetching
- Handle HTTP errors (check response.ok)
- Handle network errors (try-catch around the fetch)
- Display data in the page using safe DOM methods (createElement + textContent)
- Show a user-friendly error message if the fetch fails
- Add a timeout (abort after 10 seconds using AbortController)
Vanilla JavaScript, no dependencies.
Loading, Error, and Empty States
Every data-driven feature needs three states beyond the happy path:
Write vanilla JavaScript to manage UI states for an API-powered feature:
States to handle:
1. Loading: Show a spinner/skeleton while data loads
2. Success: Display the data
3. Error: Show a friendly message with a retry button
4. Empty: Show a "no results" message when the API returns an empty array
Requirements:
- Single function that manages state transitions
- Retry button re-fetches the data
- Loading spinner is accessible (aria-live="polite" announcement)
- Error messages don't expose technical details to users
Provide the HTML structure, CSS for each state, and JavaScript.
✅ Quick Check: Why handle the “empty” state separately from “success”?
Because an empty result is different from success with data. If a user searches for “xyzabc” and gets no results, showing them a blank page feels broken. Showing “No results found for ‘xyzabc’ — try a different search term” tells them the search worked but nothing matched. The empty state is a communication opportunity: help the user understand what happened and what to try next.
Search and Filter Interfaces
Client-Side Search
Write a real-time search filter in vanilla JavaScript:
Data: An array of objects displayed as cards on the page
Search behavior:
- Filter as the user types (debounced, 300ms delay)
- Search across multiple fields: [title, description, category]
- Case-insensitive matching
- Show result count ("Showing X of Y items")
- Show "No results" message when nothing matches
- Clear button to reset the search
Requirements:
- Debounce the input handler (don't filter on every keystroke)
- Highlight matching text in results (wrap matches in a mark element)
- Maintain URL state (add search query as URL parameter so it survives refresh)
- Accessible: announce result count changes to screen readers
Vanilla JavaScript, no dependencies.
Multi-Filter Interface
Write a filter system for a listing page:
Filter types:
- Category (checkboxes, multiple selection)
- Difficulty (radio buttons, single selection)
- Sort (dropdown: newest, oldest, alphabetical)
Requirements:
- Filters combine with AND logic (category AND difficulty)
- URL updates with filter state (shareable filter URLs)
- Active filter count displayed ("3 filters active")
- "Clear all filters" button
- Smooth transition when items show/hide
- Filter counts update to show available items per option
Vanilla JavaScript, no dependencies.
Building Common Interactive Components
Tabs
Write an accessible tabs component in vanilla JavaScript:
Requirements:
- Tab list with role="tablist"
- Tab buttons with role="tab", aria-selected, aria-controls
- Tab panels with role="tabpanel", aria-labelledby
- Keyboard navigation: Arrow keys move between tabs, Enter/Space selects
- Only the selected tab panel is visible
- Support for dynamic tab content (loaded on tab switch)
Follow WAI-ARIA Tabs pattern. Vanilla JavaScript, no dependencies.
Modal/Dialog
Write an accessible modal dialog in vanilla JavaScript:
Requirements:
- Opens on trigger button click
- Traps focus inside the modal (Tab cycles through modal elements only)
- Closes on Escape key, overlay click, and close button
- Returns focus to trigger button when closed
- Uses role="dialog" and aria-modal="true"
- Prevents background scroll when open
- Smooth open/close animation with CSS
Follow WAI-ARIA Dialog pattern. Vanilla JavaScript, no dependencies.
✅ Quick Check: Why is focus trapping important in modals?
Without focus trapping, a keyboard user pressing Tab in a modal eventually tabs through the invisible background page. They can interact with buttons and links they can’t see behind the modal overlay. This is confusing, potentially dangerous (they might submit a form they didn’t intend to), and violates accessibility guidelines. Focus trapping ensures keyboard users stay in the modal until they deliberately close it.
Exercise: Build a Dynamic Feature
- Create a search-and-filter interface for a listing of items (at least 12 items)
- Fetch data from a free public API (e.g., JSONPlaceholder) with loading and error states
- Build an accessible tabs component for organizing content
- Ensure all features work with keyboard-only navigation
- Test the error state by temporarily using a wrong API URL
Key Takeaways
- async/await makes API calls readable and debuggable — prefer it over nested .then() chains
- Every API call needs three states: loading (spinner), error (friendly message + retry), and empty (helpful guidance)
- Never expose API keys in client-side code — use a server-side proxy for any authenticated API calls
- Debounce search inputs (300ms delay) to avoid filtering on every keystroke, which hurts performance
- Interactive components (tabs, modals, accordions) must follow WAI-ARIA patterns for keyboard and screen reader accessibility
- Update the URL with filter/search state so users can share and bookmark specific views
Up Next: In the next lesson, you’ll master debugging and performance optimization — finding bugs faster and making your sites load instantly.
Knowledge Check
Complete the quiz above first
Lesson completed!