jQuery & DOM Manipulation

AJAX with jQuery - Part 2

15 min Lesson 27 of 30

jQuery AJAX Shorthand Methods

jQuery provides convenient shorthand methods for common AJAX operations. These methods simplify your code and make it more readable, while still providing powerful functionality.

$.get() Method

The $.get() method is a shorthand for making GET requests:

Basic Syntax:
$.get(url, data, callback, dataType);

// Example
$.get('/api/users', { page: 1 }, function(data) {
    console.log('Users:', data);
}, 'json');
Practical Example: Loading Products
<div id="products-container"></div>
<button id="load-products">Load Products</button>

<script>
$('#load-products').click(function() {
    // Simple GET request
    $.get('https://fakestoreapi.com/products', function(products) {
        var html = '';
        products.slice(0, 5).forEach(function(product) {
            html += '<div class="product-card">' +
                    '<h4>' + product.title + '</h4>' +
                    '<p>Price: $' + product.price + '</p>' +
                    '<p>' + product.description.substring(0, 100) + '...</p>' +
                    '</div>';
        });
        $('#products-container').html(html);
    });
});
</script>

$.post() Method

The $.post() method is a shorthand for making POST requests:

Basic Syntax:
$.post(url, data, callback, dataType);

// Example
$.post('/api/register', { username: 'john', email: 'john@example.com' }, function(response) {
    console.log('Registered:', response);
}, 'json');
Example: Submitting Form Data
<form id="contact-form">
    <input type="text" name="name" placeholder="Name" required>
    <input type="email" name="email" placeholder="Email" required>
    <textarea name="message" placeholder="Message" required></textarea>
    <button type="submit">Send Message</button>
</form>
<div id="form-message"></div>

<script>
$('#contact-form').submit(function(e) {
    e.preventDefault();

    var formData = {
        name: $('[name="name"]').val(),
        email: $('[name="email"]').val(),
        message: $('[name="message"]').val()
    };

    $.post('/api/contact', formData)
        .done(function(response) {
            $('#form-message').html(
                '<div class="success">Message sent successfully!</div>'
            );
            $('#contact-form')[0].reset();
        })
        .fail(function() {
            $('#form-message').html(
                '<div class="error">Failed to send message. Please try again.</div>'
            );
        });
});
</script>

$.getJSON() Method

The $.getJSON() method is specifically designed for fetching JSON data:

Example: Loading Weather Data
<div id="weather">
    <button id="get-weather">Get Weather</button>
    <div id="weather-info"></div>
</div>

<script>
$('#get-weather').click(function() {
    var city = 'London';
    var apiKey = 'your-api-key';
    var url = 'https://api.openweathermap.org/data/2.5/weather';

    $.getJSON(url, {
        q: city,
        appid: apiKey,
        units: 'metric'
    }, function(data) {
        var html = '<h3>' + data.name + '</h3>' +
                  '<p>Temperature: ' + data.main.temp + '°C</p>' +
                  '<p>Weather: ' + data.weather[0].description + '</p>' +
                  '<p>Humidity: ' + data.main.humidity + '%</p>';
        $('#weather-info').html(html);
    });
});
</script>

$.load() Method

The $.load() method loads HTML from a server and inserts it directly into selected elements:

Example: Loading Partial Content
<div id="header"></div>
<div id="sidebar"></div>
<div id="content"></div>

<script>
// Load complete files
$('#header').load('/templates/header.html');
$('#sidebar').load('/templates/sidebar.html');

// Load specific portion using selector
$('#content').load('/page.html #main-content');

// Load with callback
$('#content').load('/article.html', function(response, status, xhr) {
    if (status === 'error') {
        $(this).html('<p>Sorry, content could not be loaded.</p>');
    } else {
        console.log('Content loaded successfully');
    }
});

// Load with parameters
$('#results').load('/search.php', { query: 'jquery', limit: 10 });
</script>
Tip: The $.load() method is unique because it's called on a jQuery selection, not on $ directly. It automatically inserts the response into the matched elements.

Promise Interface with .done(), .fail(), .always()

All jQuery AJAX methods return a jqXHR object that implements the Promise interface:

Example: Using Promise Methods
// Basic promise chain
$.get('/api/user/1')
    .done(function(data) {
        console.log('Success:', data);
    })
    .fail(function(xhr, status, error) {
        console.log('Error:', error);
    })
    .always(function() {
        console.log('Request completed');
    });

// Multiple handlers
var request = $.getJSON('/api/products');

request.done(function(products) {
    console.log('Loaded', products.length, 'products');
});

request.done(function(products) {
    $('#product-count').text(products.length);
});

request.fail(function() {
    $('#error-message').show();
});

request.always(function() {
    $('#loader').hide();
});

Chaining Multiple AJAX Requests

Example: Sequential Requests
// Load user, then load their posts, then load comments
$.get('/api/user/1')
    .done(function(user) {
        console.log('User:', user.name);
        $('#user-name').text(user.name);

        return $.get('/api/user/' + user.id + '/posts');
    })
    .done(function(posts) {
        console.log('Posts:', posts.length);
        $('#post-count').text(posts.length);

        return $.get('/api/posts/' + posts[0].id + '/comments');
    })
    .done(function(comments) {
        console.log('Comments:', comments.length);
        $('#comment-count').text(comments.length);
    })
    .fail(function(error) {
        console.log('Error in chain:', error);
    });

Parallel AJAX Requests with $.when()

Use $.when() to execute code after multiple AJAX requests complete:

Example: Loading Multiple Resources
// Execute multiple requests in parallel
var usersRequest = $.get('/api/users');
var productsRequest = $.get('/api/products');
var categoriesRequest = $.get('/api/categories');

$.when(usersRequest, productsRequest, categoriesRequest)
    .done(function(usersData, productsData, categoriesData) {
        // All three requests completed successfully
        var users = usersData[0];      // First element is the data
        var products = productsData[0];
        var categories = categoriesData[0];

        console.log('Users:', users.length);
        console.log('Products:', products.length);
        console.log('Categories:', categories.length);

        // Initialize dashboard with all data
        initDashboard(users, products, categories);
    })
    .fail(function() {
        console.log('One or more requests failed');
        $('#error-message').text('Failed to load dashboard data');
    })
    .always(function() {
        $('#loader').hide();
    });

function initDashboard(users, products, categories) {
    $('#total-users').text(users.length);
    $('#total-products').text(products.length);
    $('#total-categories').text(categories.length);
}

Global AJAX Event Handlers

jQuery provides global AJAX events that fire for all AJAX requests:

Example: Global Loading Indicator
<div id="global-loader" style="display: none;">Loading...</div>

<script>
// Show loader when any AJAX request starts
$(document).ajaxStart(function() {
    $('#global-loader').fadeIn();
});

// Hide loader when all AJAX requests complete
$(document).ajaxStop(function() {
    $('#global-loader').fadeOut();
});

// Track AJAX activity
var activeRequests = 0;

$(document).ajaxSend(function(event, xhr, settings) {
    activeRequests++;
    console.log('Request started:', settings.url);
    console.log('Active requests:', activeRequests);
});

$(document).ajaxComplete(function(event, xhr, settings) {
    activeRequests--;
    console.log('Request completed:', settings.url);
    console.log('Active requests:', activeRequests);
});

// Global error handler
$(document).ajaxError(function(event, xhr, settings, error) {
    console.error('AJAX Error:', settings.url, error);
    if (xhr.status === 401) {
        window.location.href = '/login';
    }
});

// Global success handler
$(document).ajaxSuccess(function(event, xhr, settings) {
    console.log('AJAX Success:', settings.url);
});
</script>

AJAX Caching

Example: Implementing Cache for API Calls
var cache = {};

function getCachedData(url, forceRefresh) {
    // Check if cached and not forcing refresh
    if (cache[url] && !forceRefresh) {
        console.log('Returning cached data for:', url);
        return $.Deferred().resolve(cache[url]).promise();
    }

    // Fetch from server
    console.log('Fetching from server:', url);
    return $.get(url).done(function(data) {
        cache[url] = data;
    });
}

// Usage
$('#load-users').click(function() {
    getCachedData('/api/users')
        .done(function(users) {
            displayUsers(users);
        });
});

$('#refresh-users').click(function() {
    getCachedData('/api/users', true)  // Force refresh
        .done(function(users) {
            displayUsers(users);
        });
});

// Cache with expiration
var cacheWithExpiry = {};

function getCachedDataWithExpiry(url, ttl) {
    var now = Date.now();
    var cached = cacheWithExpiry[url];

    // Check if cached and not expired
    if (cached && (now - cached.timestamp < ttl)) {
        console.log('Returning cached data');
        return $.Deferred().resolve(cached.data).promise();
    }

    // Fetch from server
    return $.get(url).done(function(data) {
        cacheWithExpiry[url] = {
            data: data,
            timestamp: now
        };
    });
}

// Cache for 5 minutes (300000 ms)
getCachedDataWithExpiry('/api/products', 300000)
    .done(function(products) {
        displayProducts(products);
    });

Request Cancellation

Example: Cancelling Ongoing Requests
var currentRequest = null;

$('#search-input').on('input', function() {
    var query = $(this).val();

    // Cancel previous request if still running
    if (currentRequest) {
        currentRequest.abort();
        console.log('Previous request cancelled');
    }

    // Don't search if query is too short
    if (query.length < 3) {
        $('#search-results').empty();
        return;
    }

    // Start new request
    currentRequest = $.get('/api/search', { q: query })
        .done(function(results) {
            displaySearchResults(results);
        })
        .fail(function(xhr) {
            if (xhr.statusText === 'abort') {
                console.log('Request was aborted');
            } else {
                console.log('Search failed');
            }
        })
        .always(function() {
            currentRequest = null;
        });
});

function displaySearchResults(results) {
    var html = '';
    results.forEach(function(result) {
        html += '<div class="result-item">' + result.title + '</div>';
    });
    $('#search-results').html(html);
}

Default AJAX Settings

Example: Configuring Global Defaults
// Set default options for all AJAX requests
$.ajaxSetup({
    timeout: 10000,
    cache: false,
    headers: {
        'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
    },
    beforeSend: function(xhr) {
        var token = localStorage.getItem('auth_token');
        if (token) {
            xhr.setRequestHeader('Authorization', 'Bearer ' + token);
        }
    },
    error: function(xhr) {
        if (xhr.status === 401) {
            console.log('Unauthorized - redirecting to login');
            window.location.href = '/login';
        }
    }
});

// All subsequent AJAX calls will use these defaults
$.get('/api/protected-resource')
    .done(function(data) {
        console.log('Data:', data);
    });
Warning: Use $.ajaxSetup() with caution. Global defaults affect ALL AJAX requests in your application. It's often better to create wrapper functions for specific use cases.

Working with Different Content Types

Example: Sending Different Data Formats
// Sending JSON
$.ajax({
    url: '/api/data',
    method: 'POST',
    contentType: 'application/json',
    data: JSON.stringify({ name: 'John', age: 30 }),
    success: function(response) {
        console.log('JSON sent successfully');
    }
});

// Sending form-encoded data (default)
$.ajax({
    url: '/api/data',
    method: 'POST',
    data: { name: 'John', age: 30 },
    success: function(response) {
        console.log('Form data sent successfully');
    }
});

// Sending FormData (for file uploads)
var formData = new FormData();
formData.append('name', 'John');
formData.append('file', $('#file-input')[0].files[0]);

$.ajax({
    url: '/api/upload',
    method: 'POST',
    data: formData,
    processData: false,
    contentType: false,
    success: function(response) {
        console.log('File uploaded successfully');
    }
});
Practice Exercise:

Build a multi-step data loading dashboard:

  1. Create three parallel requests to load users, posts, and comments using $.when()
  2. Display a global loading indicator while requests are in progress
  3. Show statistics: total users, posts, and comments
  4. Implement caching with 2-minute expiration
  5. Add a "Refresh" button to force reload from server
  6. Display the most active user (user with most posts)
  7. Show recent posts with comment counts
  8. Handle errors gracefully and show appropriate messages

API Endpoints:

  • Users: https://jsonplaceholder.typicode.com/users
  • Posts: https://jsonplaceholder.typicode.com/posts
  • Comments: https://jsonplaceholder.typicode.com/comments

Summary

In this lesson, you learned:

  • jQuery's shorthand AJAX methods: $.get(), $.post(), $.getJSON(), $.load()
  • Using the Promise interface with .done(), .fail(), and .always()
  • Chaining sequential AJAX requests
  • Making parallel requests with $.when()
  • Global AJAX event handlers for tracking all requests
  • Implementing caching strategies
  • Cancelling ongoing requests
  • Setting global AJAX defaults with $.ajaxSetup()
  • Working with different content types

Next, we'll explore working with forms and serialization to efficiently collect and send form data via AJAX.