Module 8

Fetching Data From an API

  • GET vs POST (Client-Side Only)
    GET is for reading data. POST is for sending data (like form inputs).
  • API Keys
    Think of it like a password for accessing an API. We send it in headers or query params.
  • How JSON Works Over the Web
    JSON (JavaScript Object Notation) is the standard format for sending data over the internet:
    • Serialization: Converting JavaScript objects to JSON strings for transmission
      // JavaScript object
      const user = { name: "John", age: 25, email: "john@example.com" };
      
      // Serialized to JSON string
      const jsonString = JSON.stringify(user);
      // Result: '{"name":"John","age":25,"email":"john@example.com"}'
    • Deserialization: Converting JSON strings back to JavaScript objects
      // JSON string received from server
      const jsonResponse = '{"id":1,"name":"John","status":"active"}';
      
      // Deserialized to JavaScript object
      const userData = JSON.parse(jsonResponse);
      // Result: { id: 1, name: "John", status: "active" }
    • Data Transfer Process:
      1. Client creates JavaScript object with data
      2. Object is serialized to JSON string using JSON.stringify()
      3. JSON string is sent over HTTP request
      4. Server receives JSON string and deserializes it
      5. Server processes the data and sends JSON response
      6. Client receives JSON response and deserializes it
    • Why JSON? Universal format that works across all programming languages and platforms
  • Breaking Down a Request
    Every HTTP request has these key components:
    • URL: The web address where you're sending the request (e.g., https://api.example.com/users)
    • Method: The type of action you want to perform:
      • GET - Retrieve data (like reading a webpage)
      • POST - Send/create new data (like submitting a form)
      • PUT - Update existing data completely
      • PATCH - Update part of existing data
      • DELETE - Remove data
    • Headers: Additional information sent with the request:
      • Content-Type - Tells server what type of data you're sending (JSON, form data, etc.)
      • Authorization - API keys, tokens, or login credentials
      • User-Agent - Information about your browser/app
    • Body (optional): The actual data you're sending (only for POST, PUT, PATCH requests)
    • Query Parameters: Data added to the URL after ? (e.g., ?page=1&limit=10)
    Example Request as JSON:
    {
      "url": "https://api.example.com/users",
      "method": "POST",
      "headers": {
        "Content-Type": "application/json",
        "Authorization": "Bearer your-api-key-here",
        "User-Agent": "MyApp/1.0"
      },
      "body": {
        "name": "John Doe",
        "email": "john@example.com",
        "age": 25
      },
      "queryParams": {
        "page": 1,
        "limit": 10
      }
    }
  • Async/Await Refresher + Axios
    Fetch API: Built-in browser method for making HTTP requests
    // GET request with fetch
    async function getData() {
      try {
        const response = await fetch('https://api.example.com/data');
        const data = await response.json();
        console.log(data);
      } catch (error) {
        console.error('Error:', error);
      }
    }
    
    // POST request with fetch
    async function postData() {
      try {
        const response = await fetch('https://api.example.com/data', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({ name: 'John', age: 30 })
        });
        const result = await response.json();
        console.log(result);
      } catch (error) {
        console.error('Error:', error);
      }
    }
    Axios: Popular third-party library for HTTP requests (more features)
    // GET request with axios
    async function getDataAxios() {
      try {
        const response = await axios.get('https://api.example.com/data');
        console.log(response.data);
      } catch (error) {
        console.error('Error:', error);
      }
    }
    
    // POST request with axios
    async function postDataAxios() {
      try {
        const response = await axios.post('https://api.example.com/data', {
          name: 'John',
          age: 30
        });
        console.log(response.data);
      } catch (error) {
        console.error('Error:', error);
      }
    }
    Key Differences:
    • Fetch: Built-in, requires manual JSON parsing, no automatic error handling
    • Axios: Third-party, automatic JSON parsing, better error handling, request/response interceptors
  • Simple Flow Explanation
    Client ➡️ Request ➡️ Server evaluates ➡️ Response ➡️ Client receives
  • POST Requests & Testing Endpoints
    POST requests are used to send data to servers (create, update, submit forms):
    • When to use POST: Creating new data, submitting forms, uploading files, authentication
    • Data in Body: POST requests include data in the request body (not URL)
    • Headers Required: Usually need Content-Type: application/json
    Testing API Endpoints:
    Use tools to test your API requests before coding:
    • Postman: Popular GUI tool for API testing
    • Insomnia: Lightweight alternative to Postman
    • Thunder Client: VS Code extension for API testing
    • cURL: Command-line tool for making requests
    📥 Download Postman (Free) Great for testing GET, POST, PUT, DELETE requests!

Live Example: Fetch Brewery Data

Click the button below to see a real fetch request in action. Open your browser's console (F12) to see the detailed steps!

TODO: Add an input field to let users search for breweries in any city!

Bootstrap and Tailwind CSS

  • Overview
    Both are UI libraries that help you style without writing CSS from scratch. But why do we use them instead of writing our own CSS?
    • Time Efficiency: Pre-built components save hours of development time
    • Consistency: Ensures your app looks professional across all pages
    • Responsive Design: Automatically works on mobile, tablet, and desktop
    • Cross-Browser Compatibility: Tested to work on all major browsers
    • Best Practices: Built by experts with accessibility and performance in mind
  • Using Bootstrap CDN
    No install needed, just link to the stylesheet like we did in this HTML.
  • What is a CDN?
    A fast network to load shared files (like Bootstrap) from servers close to the user.
  • Bootstrap vs Tailwind
    Bootstrap: Gives you pre-made components (buttons, cards, modals) that you can use immediately. Think of it like LEGO blocks - you get complete pieces that you can customize.

    Tailwind: Gives you low-level utility classes that you combine to build anything. Think of it like individual LEGO pieces - you have complete control but need to build from scratch.

    When to choose which:
    • Choose Bootstrap: When you want to build fast, need consistent components, or are new to CSS
    • Choose Tailwind: When you want complete design control, need custom designs, or prefer utility-first approach
  • Semantic-based Class Naming
    Tailwind's classes describe *what* it does (bg-blue-500), not where.
  • Real-World Benefits
    • Faster Development: Build a professional-looking website in hours instead of days
    • Team Collaboration: Everyone uses the same design system and components
    • Maintenance: Updates and bug fixes are handled by the framework team
    • Performance: Optimized CSS that loads quickly and efficiently
    • Accessibility: Built-in support for screen readers and keyboard navigation
    • Mobile-First: Designed to work perfectly on mobile devices from the start
    • Documentation: Extensive documentation and community support

📚 Documentation & Resources

Bootstrap
📖 Bootstrap Documentation Official Bootstrap 5 documentation with examples and components
Tailwind CSS
📖 Tailwind Documentation Complete Tailwind CSS documentation with utility classes

Recursive Functions

  • What is Recursion?
    A function that calls itself. Must have a base case to avoid infinite loops.
  • How They Work
    Think of breaking a problem into smaller problems until it’s solvable (base case).
  • Real-World Examples
    • Fibonacci sequence
    • Folder/file structure traversal
    • Calculating factorials
    • DOM tree manipulation

🧮 Live Example: Recursive Factorial

Enter a number to see how recursion works step by step. Open your browser's console (F12) to see the recursive process!

How it works: The function calls itself with a smaller number until it reaches the base case (0 or 1), then multiplies all the numbers together.
📝 The Recursive Function Code:
// Recursive function example: Calculate factorial
function factorial(n) {
    console.log(`🔍 Calculating factorial(${n})...`);
    
    // Base case: factorial of 0 or 1 is 1
    if (n === 0 || n === 1) {
        console.log(`✅ Base case reached! factorial(${n}) = 1`);
        return 1;
    }
    
    // Recursive case: n! = n × (n-1)!
    console.log(`🔄 Recursive case: ${n}! = ${n} × (${n-1})!`);
    const result = n * factorial(n - 1);
    console.log(`📊 factorial(${n}) = ${n} × ${result/n} = ${result}`);
    return result;
}
🔑 Key Concepts:
  • Base Case: The stopping condition (n === 0 or 1)
  • Recursive Case: The function calls itself with a smaller value
  • Call Stack: Each recursive call adds to the stack
  • Return Values: Results bubble back up through the stack
📊 Example: factorial(3)
  1. factorial(3) calls factorial(2)
  2. factorial(2) calls factorial(1)
  3. factorial(1) returns 1 (base case)
  4. factorial(2) returns 2 × 1 = 2
  5. factorial(3) returns 3 × 2 = 6

🍺 Brewery Finder DEMO

In this session, we'll build a complete brewery finder application using vanilla JavaScript and the Open Brewery DB API.

🎯 See the Finished Product!

Check out the complete brewery finder application before we build it together:

🍺 View Live Demo Opens in a new tab - explore the features and functionality!

🎯 Core Deliverables

  • Search Functionality:
    • Search breweries by city OR by name (toggleable search type)
    • Use the Open Brewery DB API: https://api.openbrewerydb.org/v1/breweries
    • Real-time search with debouncing (prevent excessive API calls)
  • Results Display:
    • Display maximum 12 results per page
    • Pagination controls (Previous/Next buttons)
    • Show current page number and total results count
    • Responsive grid layout for brewery cards
  • Error Handling & Validation:
    • Input field validation (required fields, minimum characters)
    • Display "No results found" when search returns empty
    • Show "Error occurred processing your request" for API failures
    • Network error handling (offline, timeout, server errors)
    • Loading states and spinners during API calls
  • User Experience:
    • Clean, intuitive interface with Bootstrap styling
    • Clear search results with brewery details (name, type, location, website)
    • Clickable brewery cards with hover effects
    • Search history or recent searches

📚 Learning Objectives

  • API Integration:
    • Working with external APIs
    • URL parameter construction
    • Response handling and data parsing
  • DOM Manipulation:
    • Dynamic content creation
    • Event handling and listeners
    • Form validation and submission
  • State Management:
    • Managing application state
    • Pagination logic
    • Search history tracking
  • Error Handling:
    • Try-catch blocks
    • User-friendly error messages
    • Graceful degradation
  • Performance:
    • Debouncing search inputs
    • Efficient DOM updates
    • Loading state management

🛠️ Technical Implementation

Frontend Technologies:
  • HTML5: Semantic structure, forms, accessibility
  • CSS3: Flexbox/Grid, animations, responsive design
  • Vanilla JavaScript: ES6+ features, async/await, modules
  • Bootstrap 5: Components, utilities, responsive grid
Key JavaScript Concepts:
  • Fetch API: Making HTTP requests
  • Event Handling: Click, input, form events
  • DOM Methods: querySelector, createElement, appendChild
  • Array Methods: map, filter, slice for pagination
  • Local Storage: Saving search history

🎯 Bonus Features (If Time Permits)

  • Advanced Search: Filter by brewery type (micro, brewpub, large, etc.)
  • Sorting Options: Sort results by name, city, or brewery type
  • Favorites System: Save favorite breweries to local storage
  • Map Integration: Show brewery locations on a map (using coordinates from API)
  • Responsive Design: Mobile-first approach with touch-friendly interactions