Creating an Upload Form with AJAX and JavaScript

HTML Form Structure
Starting with creating a form with the "multipart/form-data" enctype, which is essential for file uploads. The form consists of:
- Title: For entering filename or subject
- Description: For additional details
- Category: Dropdown for selecting file type
- File Input: For selecting files to upload
- Progress Bar: Shows upload progress
- Submit Button: For submitting data
<form id="uploadForm" enctype="multipart/form-data">
<div class="form-group">
<label for="title">Title:</label>
<input type="text" id="title" name="title" required>
</div>
<div class="form-group">
<label for="description">Description:</label>
<textarea id="description" name="description" rows="3"></textarea>
</div>
<div class="form-group">
<label for="category">Category:</label>
<select id="category" name="category">
<option value="">Select category</option>
<option value="documents">Documents</option>
<option value="images">Images</option>
<option value="videos">Videos</option>
</select>
</div>
<div class="form-group">
<label for="fileInput">File:</label>
<input type="file" id="fileInput" name="file" required>
<small class="file-info">Max file size: 10MB</small>
</div>
<div class="progress-container" style="display: none;">
<div class="progress-bar" id="progressBar">
<div class="progress" style="width: 0%"></div>
</div>
<div class="progress-text">0%</div>
</div>
<button type="submit" id="submitBtn">Upload</button>
</form>
Form Submit Handling
When users click the Submit button, the following processes occur:
- Prevent default form submission using preventDefault()
- Validate data (Validation)
- Create a FormData object to store all form data
- Create XMLHttpRequest for AJAX submission
- Display progress bar and disable submit button
- Send data to server
/**
* File Upload Handler
* Handles file upload using Ajax with progress tracking and validation
*/
document.getElementById('uploadForm').addEventListener('submit', function(e) {
e.preventDefault();
// Validate form
if (!validateForm()) {
return;
}
// Get form elements
const fileInput = document.getElementById('fileInput');
const title = document.getElementById('title').value;
const description = document.getElementById('description').value;
const category = document.getElementById('category').value;
const submitBtn = document.getElementById('submitBtn');
const progressContainer = document.querySelector('.progress-container');
const progressBar = document.querySelector('.progress');
const progressText = document.querySelector('.progress-text');
// Create FormData object
const formData = new FormData();
formData.append('file', fileInput.files[0]);
formData.append('title', title);
formData.append('description', description);
formData.append('category', category);
// Create XMLHttpRequest object
const xhr = new XMLHttpRequest();
// Show progress container and disable submit button
progressContainer.style.display = 'block';
submitBtn.disabled = true;
/**
* Track upload progress
* @param {ProgressEvent} e - Progress event object
*/
xhr.upload.addEventListener('progress', function(e) {
if (e.lengthComputable) {
const percentComplete = Math.round((e.loaded / e.total) * 100);
progressBar.style.width = percentComplete + '%';
progressText.textContent = percentComplete + '%';
}
});
/**
* Handle successful upload
* @param {Event} e - Load event object
*/
xhr.addEventListener('load', function(e) {
submitBtn.disabled = false;
if (xhr.status === 200) {
showMessage('success', 'File uploaded successfully!');
resetForm();
} else {
showMessage('error', 'Upload failed. Status: ' + xhr.status);
}
progressContainer.style.display = 'none';
});
/**
* Handle upload error
* @param {Event} e - Error event object
*/
xhr.addEventListener('error', function(e) {
submitBtn.disabled = false;
showMessage('error', 'An error occurred during upload.');
progressContainer.style.display = 'none';
});
// Configure and send request
xhr.open('POST', '/upload.php', true);
xhr.send(formData);
});
/**
* Validate form inputs
* @returns {boolean} - Validation result
*/
function validateForm() {
const title = document.getElementById('title').value;
const fileInput = document.getElementById('fileInput');
const file = fileInput.files[0];
if (!title.trim()) {
showMessage('error', 'Please enter a title');
return false;
}
if (!file) {
showMessage('error', 'Please select a file');
return false;
}
// Check file size (10MB limit)
if (file.size > 10 * 1024 * 1024) {
showMessage('error', 'File size must be less than 10MB');
return false;
}
return true;
}
/**
* Show message to user
* @param {string} type - Message type (success/error)
* @param {string} message - Message text
*/
function showMessage(type, message) {
alert(message); // You can replace this with a better UI notification
}
/**
* Reset form to initial state
*/
function resetForm() {
document.getElementById('uploadForm').reset();
document.querySelector('.progress').style.width = '0%';
document.querySelector('.progress-text').textContent = '0%';
}
Progress Tracking
During upload, progress is tracked through XMLHttpRequest's "progress" event:
- Calculate percentage from e.loaded and e.total
- Update progress bar and percentage text
- Display real-time progress to users
Data Validation
The validateForm() function checks:
- Title must not be empty
- File must be selected
- File size must not exceed 10MB
Result Handling
After upload completion, status is handled as follows:
- Success case (status 200):
- Display success message
- Reset form
- Hide progress bar
- Error case:
- Show error message
- Enable submit button
- Hide progress bar
CSS Styling
Form appearance is managed using CSS, handling:
- Form elements layout
- Progress bar styling
- Input fields enhancement
- Responsive design implementation
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
margin-bottom: 5px;
}
.form-group input[type="text"],
.form-group textarea,
.form-group select {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
}
.progress-container {
margin: 15px 0;
}
.progress-bar {
width: 100%;
height: 20px;
background-color: #f0f0f0;
border-radius: 10px;
overflow: hidden;
}
.progress {
height: 100%;
background-color: #4CAF50;
transition: width 0.3s ease-in-out;
}
.file-info {
display: block;
color: #666;
font-size: 12px;
margin-top: 5px;
}
button {
padding: 10px 20px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background-color: #45a049;
}
button:disabled {
background-color: #cccccc;
cursor: not-allowed;
}
Implementation
For actual implementation, a PHP file (upload.php) must be created to handle uploaded files, checking:
- Allowed file types
- Maximum file size
- Available storage space
- Access permissions
Summary
Creating an Upload Form with AJAX allows users to upload files without page refresh and view upload progress in real-time. Using JavaScript for validation and UI management enhances the user experience.