Creating a Progressive Web App (PWA) to store contact details from a form and submit them when internet access is available involves a combination of technologies like HTML, CSS, JavaScript, and service workers. Below is a simplified example of how you can achieve this:
- HTML Form: Create an HTML form to collect contact details. You can create an
index.html
file.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Contact Details Form</title>
</head>
<body>
<h1>Contact Details</h1>
<form id="contactForm">
<label for="name">Name:</label>
<input type="text" id="name" name="name" required><br>
<label for="email">Email:</label>
<input type="email" id="email" name="email" required><br>
<label for="phone">Phone:</label>
<input type="tel" id="phone" name="phone" required><br>
<button type="submit">Submit</button>
</form>
<script src="app.js"></script>
</body>
</html>
- JavaScript: Create a JavaScript file (
app.js
) to handle form submission and store data locally when there's no internet access.
// Check if service workers are supported
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('service-worker.js')
.then(function(registration) {
console.log('Service Worker registered with scope:', registration.scope);
})
.catch(function(error) {
console.error('Service Worker registration failed:', error);
});
}
const contactForm = document.getElementById('contactForm');
contactForm.addEventListener('submit', function(event) {
event.preventDefault();
const name = document.getElementById('name').value;
const email = document.getElementById('email').value;
const phone = document.getElementById('phone').value;
// Create a JSON object with the contact details
const contact = {
name,
email,
phone,
};
// Check if there's internet access
if (navigator.onLine) {
// If online, send data to the server
sendDataToServer(contact);
} else {
// If offline, store data locally
storeDataLocally(contact);
}
// Clear the form
contactForm.reset();
});
function sendDataToServer(contact) {
// Implement code to send data to the server using fetch or another method
// Example: fetch('/api/contacts', { method: 'POST', body: JSON.stringify(contact) });
}
function storeDataLocally(contact) {
// Store data locally, e.g., in IndexedDB or localStorage
// You can use a library like Dexie.js for IndexedDB
// Example: indexedDB.put('contacts', contact);
}
- Service Worker: Create a service worker (
service-worker.js
) to cache assets and handle offline functionality. It should be placed in the root directory of your project.
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open('contact-app-cache').then(function(cache) {
return cache.addAll([
// Add the URLs of your assets to cache here
'/',
'/index.html',
'/app.js',
// Add more URLs as needed
]);
})
);
});
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request).then(function(response) {
return response || fetch(event.request);
})
);
});
- Manifest File: Create a
manifest.json
file to specify your PWA's metadata. This file should be included in the HTML file to enable the PWA features.
{
"name": "Contact App",
"short_name": "Contacts",
"description": "Store and submit contact details",
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#000000",
"icons": [
{
"src": "icon.png",
"sizes": "192x192",
"type": "image/png"
}
]
}
-
Icon: Create an icon (e.g.,
icon.png
) for your PWA and place it in the root directory. -
Testing: Test your PWA locally and deploy it to a web server with HTTPS for a more secure experience.
This is a basic example to get you started with a PWA for storing and submitting contact details when internet access is available. Depending on your requirements, you may need to enhance error handling, implement synchronization strategies, and secure data storage.
To store data locally using IndexedDB in your Progressive Web App (PWA), you can modify the JavaScript code from the previous example. Here's how you can store contact details locally using IndexedDB:
- Modify the JavaScript Code (app.js):
// Check if service workers are supported
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('service-worker.js')
.then(function(registration) {
console.log('Service Worker registered with scope:', registration.scope);
})
.catch(function(error) {
console.error('Service Worker registration failed:', error);
});
}
const contactForm = document.getElementById('contactForm');
// Open a connection to the IndexedDB database
const request = indexedDB.open('contactsDB', 1);
request.onupgradeneeded = function(event) {
const db = event.target.result;
// Create an object store to store contact data
const objectStore = db.createObjectStore('contacts', { keyPath: 'email' });
// Create an index to query contacts by name
objectStore.createIndex('name', 'name', { unique: false });
};
request.onerror = function(event) {
console.error('IndexedDB error:', event.target.error);
};
request.onsuccess = function(event) {
const db = event.target.result;
contactForm.addEventListener('submit', function(event) {
event.preventDefault();
const name = document.getElementById('name').value;
const email = document.getElementById('email').value;
const phone = document.getElementById('phone').value;
const contact = {
name,
email,
phone,
};
const transaction = db.transaction(['contacts'], 'readwrite');
const objectStore = transaction.objectStore('contacts');
// Add the contact to the object store
const addRequest = objectStore.add(contact);
addRequest.onsuccess = function() {
console.log('Contact added to IndexedDB:', contact);
};
addRequest.onerror = function() {
console.error('Error adding contact to IndexedDB:', addRequest.error);
};
// Clear the form
contactForm.reset();
});
};
In this code:
- We open a connection to an IndexedDB database called 'contactsDB'.
- In the 'onupgradeneeded' event, we create an object store called 'contacts' to store contact data with email as the key path. We also create an index to query contacts by name.
- In the 'onsuccess' event, we set up an event listener for the form submission. When the form is submitted, we add the contact data to the 'contacts' object store.
This code initializes and uses IndexedDB to store contact details locally in the 'contacts' object store.
Make sure to handle errors and implement retrieval and synchronization logic as needed based on your application's requirements.
To send the data stored in IndexedDB to a server when an internet connection is available, you need to implement logic that checks for internet connectivity and periodically synchronizes data between IndexedDB and your server. Here's a modification to the JavaScript code (app.js) to accomplish this:
// Check if service workers are supported
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('service-worker.js')
.then(function(registration) {
console.log('Service Worker registered with scope:', registration.scope);
})
.catch(function(error) {
console.error('Service Worker registration failed:', error);
});
}
const contactForm = document.getElementById('contactForm');
// Open a connection to the IndexedDB database
const request = indexedDB.open('contactsDB', 1);
request.onupgradeneeded = function(event) {
const db = event.target.result;
// Create an object store to store contact data
const objectStore = db.createObjectStore('contacts', { keyPath: 'email' });
// Create an index to query contacts by name
objectStore.createIndex('name', 'name', { unique: false });
};
request.onerror = function(event) {
console.error('IndexedDB error:', event.target.error);
};
request.onsuccess = function(event) {
const db = event.target.result;
contactForm.addEventListener('submit', function(event) {
event.preventDefault();
const name = document.getElementById('name').value;
const email = document.getElementById('email').value;
const phone = document.getElementById('phone').value;
const contact = {
name,
email,
phone,
};
const transaction = db.transaction(['contacts'], 'readwrite');
const objectStore = transaction.objectStore('contacts');
// Add the contact to the object store
const addRequest = objectStore.add(contact);
addRequest.onsuccess = function() {
console.log('Contact added to IndexedDB:', contact);
// Check for internet connectivity and synchronize
if (navigator.onLine) {
syncDataWithServer();
}
};
addRequest.onerror = function() {
console.error('Error adding contact to IndexedDB:', addRequest.error);
};
// Clear the form
contactForm.reset();
});
};
function syncDataWithServer() {
const db = request.result;
const transaction = db.transaction(['contacts'], 'readonly');
const objectStore = transaction.objectStore('contacts');
objectStore.getAll().onsuccess = function(event) {
const contacts = event.target.result;
// Send contacts to the server
fetch('/api/sync', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(contacts),
})
.then(function(response) {
if (response.ok) {
// Data successfully synced, you may want to remove synced data from IndexedDB
clearSyncedDataFromIndexedDB(contacts);
} else {
console.error('Failed to sync data:', response.status);
}
})
.catch(function(error) {
console.error('Error while syncing data:', error);
});
};
}
function clearSyncedDataFromIndexedDB(data) {
const db = request.result;
const transaction = db.transaction(['contacts'], 'readwrite');
const objectStore = transaction.objectStore('contacts');
data.forEach(function(contact) {
objectStore.delete(contact.email);
});
}
In this code:
-
We added a
syncDataWithServer
function to send the data stored in IndexedDB to the server using thefetch
API. Adjust the URL and request headers as needed to match your server's API. -
After successfully syncing the data with the server, we have a
clearSyncedDataFromIndexedDB
function that removes the synced data from IndexedDB. This ensures that only unsynced data remains in IndexedDB. -
When a new contact is added to IndexedDB, we check for internet connectivity (
navigator.onLine
). If there is an internet connection, we immediately attempt to sync the data with the server.
Make sure you have a server API endpoint to receive and store the data sent from the client. Additionally, you may want to implement error handling and further synchronization strategies based on your application's requirements.
To check for internet connectivity periodically every 10 minutes, you can use JavaScript's setInterval
function to run a connectivity check function at regular intervals. Here's how to modify your code to achieve this:
// ...
// Check for internet connectivity every 10 minutes (600,000 milliseconds)
const checkConnectivityInterval = 600000;
// Function to check internet connectivity
function checkConnectivity() {
if (navigator.onLine) {
syncDataWithServer(); // If online, try to sync data with the server
}
}
// Set up the periodic connectivity check
setInterval(checkConnectivity, checkConnectivityInterval);
// ...
In this code:
-
We define the
checkConnectivity
function that checks for internet connectivity (navigator.onLine
) and, if online, calls thesyncDataWithServer
function to attempt data synchronization. -
We set the
checkConnectivityInterval
to 600,000 milliseconds (10 minutes). -
We use
setInterval
to repeatedly call thecheckConnectivity
function at the specified interval, which will check for connectivity every 10 minutes.
With this modification, your application will periodically check for internet connectivity and attempt to sync data with the server when an internet connection is available. Adjust the checkConnectivityInterval
value to suit your specific requirements.
You would insert the code for checking internet connectivity every 10 minutes in your existing JavaScript file (app.js
) where you've set up the IndexedDB and handling of form submissions. Here's where you would insert the code:
// ...
// Open a connection to the IndexedDB database
const request = indexedDB.open('contactsDB', 1);
request.onupgradeneeded = function(event) {
const db = event.target.result;
// Create an object store to store contact data
const objectStore = db.createObjectStore('contacts', { keyPath: 'email' });
// Create an index to query contacts by name
objectStore.createIndex('name', 'name', { unique: false });
};
request.onerror = function(event) {
console.error('IndexedDB error:', event.target.error);
};
request.onsuccess = function(event) {
const db = event.target.result;
contactForm.addEventListener('submit', function(event) {
event.preventDefault();
const name = document.getElementById('name').value;
const email = document.getElementById('email').value;
const phone = document.getElementById('phone').value;
const contact = {
name,
email,
phone,
};
const transaction = db.transaction(['contacts'], 'readwrite');
const objectStore = transaction.objectStore('contacts');
// Add the contact to the object store
const addRequest = objectStore.add(contact);
addRequest.onsuccess = function() {
console.log('Contact added to IndexedDB:', contact);
// Check for internet connectivity and synchronize
if (navigator.onLine) {
syncDataWithServer();
}
};
addRequest.onerror = function() {
console.error('Error adding contact to IndexedDB:', addRequest.error);
};
// Clear the form
contactForm.reset();
});
// Check for internet connectivity every 10 minutes (600,000 milliseconds)
const checkConnectivityInterval = 600000;
// Function to check internet connectivity
function checkConnectivity() {
if (navigator.onLine) {
syncDataWithServer(); // If online, try to sync data with the server
}
}
// Set up the periodic connectivity check
setInterval(checkConnectivity, checkConnectivityInterval);
};
// ...
You can insert this code block after the request.onsuccess
event handler where you've been handling form submissions and data synchronization. This code will periodically check for internet connectivity and attempt to sync data with the server every 10 minutes while your PWA is running. Adjust the interval (checkConnectivityInterval
) as needed.