Share
Explore

Express with MONGO DB ROUTES lab workbook

Fun Fact: is created by . He coined the term .
More background on Mongo and Mongoose:
Watch this Explainer Video for an Overview of this Workbook:
Lab Workbook Part 1: JavaScript MONGOOSE API Code to create a Bookstore Database in Altas DB.
Lab Workbook Part 2: Front end CRUD operations on our MONGOOSE Database with Express.js.
Complete Node.js Application.
Review : mongoose express nodemon
nodemon index.js

Recalling our work in class on creating the MVC MONGO database and front ending the database with an Express.js server and html page:
Let’s make a 3 tier application to model the business domain of a bookstore:

Part 1: Make a Node.js project with code using MONGOOSE API to create a MONGO database to make a book store with collections for books, customers, and customerorders.

Make 5 book records, 5 customer records, and 3 order records relating 3 customer to the purchase of 2 books each.


To create a comprehensive Node.js full stack web application with Mongoose and MongoDB, we must structure the content effectively by considering the following components:

Create a directory and in your VSC project, remember npm -init to create the package.json
Setting up the Project: Remember to import all the packages you are using.
Creating Database Schema: Create the schemas for the collections: books, customers, and customer orders. Include schema design considerations and how they relate to real-world entities.
Seeding Data: Insert mock data into the MongoDB database. Could use MONGODB Compass or write a mongoose script. This involves creating seed files and using Mongoose models to seed the database with 5 book records, 5 customer records, and 3 order records that relate 3 customers to the purchase of 2 books each.
CRUD Queries and Operations: In this section, demonstrate how to perform CRUD operations using Mongoose, such as querying books, adding new customers, and creating customer orders. This should cover basic find, create, update, and delete operations.
Error Handling and Best Practices: Discuss best practices for error handling, data validation, and ensuring data integrity within the database. Provide examples of error handling in Mongoose and Node.js.
Documentation: Emphasize the importance of documenting code and provide guidance on writing clear, concise, and meaningful comments within the codebase.
End-to-End Project Example: Demonstrate the simple web application that interacts with the MongoDB database using Node.js and Mongoose.

Workflow to set up the Node.js project with Mongoose and create the database schemas:

Step 1: Create a project directory and initialize the Node.js project

Open the terminal and create a new directory for your project:
mkdir nodejs-bookstore cd nodejs-bookstore
Then, initialize the project using npm to generate the package.json file:
npm init
Follow the prompts to fill in the details or use the default values to create package.json.

Step 2: Setting up the Project:

Install required npm packages
You'll need to install the necessary npm packages for the project.
Run the following commands to install Mongoose and any other required packages:
npm install mongoose express mongo nodemon
Ensure mongoose and express are listed as dependencies in your package.json after installation.

Step 3: Creating Database Schema : done in file models.js

...

Option 2: Enable ES6 Modules in Node.js

If you prefer to use ES6 modules, you can configure your Node.js environment to support them:
Set "type": "module" in package.json:
Add "type": "module" to your package.json. This tells Node.js to treat JavaScript files as ES6 modules.
Your package.json should look something like this:
{ "name": "your-app", "version": "1.0.0", "type": "module", // ... other fields }
Use .mjs Extension:
Alternatively, you can use the .mjs extension for your JavaScript files if you prefer not to change the package.json settings. Simply rename your models.js to models.mjs.
After making these changes, you should be able to use the ES6 import/export syntax without encountering the error.

Note on Node.js Version

Node.js has been gradually adding support for ES6 modules, and it's fully available in recent versions. Ensure you are using a Node.js version that supports ES6 modules (Node.js version 13.2.0 or later). You are currently using Node.js v20.9.0, which supports ES6 modules, so you should be good to go once you apply one of the above options.
...



***** Create a new file called models.js, for defining the Mongoose schemas.
////////////////
The models.js file is a vital part of a typical Node.js application that uses Mongoose for database interaction.
In a real-world scenario, the models.js file would be created in a separate "models" or "db" directory within the project's directory structure. This file contains the Mongoose schema definitions for the various data entities utilized in the application, such as books, users, etc.
Here's an example of how the models.js file might be structured:
// models.js

import mongoose from 'mongoose';

const bookSchema = new mongoose.Schema({
title: String,
author: String,
genre: String,
// Other book properties...
});

const userSchema = new mongoose.Schema({
username: String,
email: String,
// Other user properties...
});

// Book and user are MODELS
// model is a in program memory data representation of an entity in the business domain that you are writing the software application to automate.

const Book = mongoose.model('Book', bookSchema);
const User = mongoose.model('User', userSchema);

export { Book, User };
In this example, models.js contains the schema definitions for the Book and User models.
These schemas define the structure of the data entities, including their properties and types.
Once created, this models.js file can be imported and utilized in other parts of the application, such as in the server-side code, to interact with the MongoDB database using Mongoose.
///////////////
In the context of Mongoose and MongoDB:
bookSchema:
bookSchema is a Mongoose schema that defines the structure of documents within the 'books' collection in MongoDB. It specifies the expected fields and their data types for each book document. In the provided example, bookSchema includes fields for the title, author, genre, and potentially other properties relating to a book entity.
userSchema:
Similarly, userSchema is a Mongoose schema that outlines the blueprint for documents within the 'users' collection in MongoDB. It defines the expected fields and their data types for each user document. In the example given, userSchema includes fields for the username, email, and possibly other properties relevant to a user entity.
Book and User:
Book and User are Mongoose models that are created using the mongoose.model method. These models are used to interact with the MongoDB collections ('books' and 'users', respectively) that adhere to the defined schemas (bookSchema and userSchema).

By creating models from these schemas, Mongoose provides an interface for conducting operations such as creating, reading, updating, and deleting (CRUD) documents in the respective collections.
bookSchema and userSchema serve as blueprints that define the expected structure and data types for documents in the 'books' and 'users' collections.

Book and User are Mongoose models that provide a way to interact with these collections, leveraging the defined schemas for streamlined and consistent data management.
The models.js file commonly defines Mongoose schemas and creates corresponding Mongoose models.

Here's a more detailed breakdown:
Schema are structures.
Models are data entities which realize those structures.
Models.js setups the schema and creates the Models.
Models are the in-memory OBJECTS we interact with in our mongoose code.
Defining Schemas: The Mongoose schemas, such as bookSchema and userSchema in the provided example, define the structure of the data entities within a MongoDB database. Schemas specify the properties, data types, validation rules, and other configuration for documents in a specific collection.
Creating Models: Mongoose models, such as Book and User, are created from the defined schemas using the mongoose.model method. These models are responsible for providing an interface for interacting with the MongoDB collections according to the defined schemas. They represent the business domain entities and handle operations like creating, reading, updating, and deleting documents in the database.
Therefore, the models.js file indeed plays a crucial role in defining the structure of the data domain, via schemas, and creating the corresponding models to handle data records within the business domain.
ECMAScript 6 Modules Import / Export

In Node.js, module imports and exports are used to encapsulate code within separate files and enable the sharing of functionality between different parts of the application.
When a file (module) is imported, its contents become available for use in the importing file.
When a file (module) is exported, it makes certain components of the file available for use in other files.
In the context of the code we've discussed, I'll explain how module imports and exports can be performed with examples based on the existing code:

Exporting from models.js:

In models.js, the Mongoose models are typically exported to make them accessible to other parts of the application. Here's how it's done using module.exports:
javascript// models.js const mongoose = require('mongoose');
const bookSchema = new mongoose.Schema({ title: String, author: String, genre: String, // Other book properties... });
const Book = mongoose.model('Book', bookSchema);
module.exports = { Book };
In this example, the Book model is defined and then exported using module.exports as an object. This makes Book available for use in other files that import models.js.

Importing into seed.js:

To utilize the exported Book model in seed.js, it can be imported using require:
seed.js
// Using ES6 import syntax
import mongoose from 'mongoose';
import { Book } from './models.js'; // Make sure the path is correct

// ... rest of your code

// Importing the Book model
// Rest of the seeding logic using the Book model
Here, the Book model is imported from models.js using the require statement, allowing seed.js to access and use the Book model for seeding the database with sample book records.
By using the require function to import and module.exports to export, we can achieve modularization and code reuse in a Node.js application.
This allows for better organization, maintainability, and reusability of the application's codebase.
I anticipate this provides a clear understanding of module imports and exports in the context of the provided code. If you have further queries or need additional examples, feel free to ask!

In the provided starter code, replace the template information with real book titles and posit some names for customers:

Include 5 book records, 5 customer records, and 3 order records.
We'll also establish the relationships between customers and their orders, as well as the books included in each order.
First, let's create the seed data for the initial records.
Create a new file, for example seed.js, to populate the database with records:

Following the methods we used in class: REPLACE THE REFERENCES TO LOCAL MONGO DB SERVER WITH THE MONGO DB REALM CREDENTIALS YOU CREATED IN CLASS ON THURSDAY.

javascript:
// seed.js// Using ES6 import syntax
import mongoose from 'mongoose';
import { Book, Customer, Order } from './models.js'; // Importing all required models
// Function to seed initial data
async function seedData() {
try {
// Create 5 book records
const books = await Book.create([
{ title: 'Book 1', author: 'Author 1' },
{ title: 'Book 2', author: 'Author 2' },
{ title: 'Book 3', author: 'Author 3' },
{ title: 'Book 4', author: 'Author 4' },
{ title: 'Book 5', author: 'Author 5' }
]);

// Create 5 customer records
const customers = await Customer.create([
{ name: 'Customer 1', email: 'customer1@example.com' },
{ name: 'Customer 2', email: 'customer2@example.com' },
{ name: 'Customer 3', email: 'customer3@example.com' },
{ name: 'Customer 4', email: 'customer4@example.com' },
{ name: 'Customer 5', email: 'customer5@example.com' }
]);

// Create 3 order records
const orders = await Order.create([
{ customer: customers[0]._id, books: [books[0]._id, books[1]._id] },
{ customer: customers[1]._id, books: [books[2]._id, books[3]._id] },
{ customer: customers[2]._id, books: [books[4]._id, books[1]._id] }
]);

console.log('Seed data created successfully');
} catch (error) {
console.error('Error seeding data:', error);
} finally {
// Close the database connection
mongoose.connection.close();
}
}

// Call the seedData function
seedData();


In the provided program, the names of the schemas and their respective schema items are:
Schema Names:
Book
Customer
Order
Schema Items:
Book Schema:
title: String (required)
author: String (required)
Customer Schema:
name: String (required)
email: String (required)
Order Schema:
customer: ObjectId (references Customer collection, required)
books: Array of ObjectIds (references Book collection, required)

In the seedData function, these schema items are utilized to create initial records for the Book, Customer, and Order collections in the MongoDB database.
Each record is created using the respective schemas defined in the models.js file.
This establishes a clear understanding of the schema names and their respective items involved in creating and populating the database records in the provided program.

In this seed file, we use the create method provided by Mongoose to insert the initial data into the respective collections.

After adding the seed data, execute the seed.js file using Node.js to populate the database with the initial records.
By incorporating this expanded code, you can fulfill the requirement of creating 5 book records, 5 customer records, and 3 order records for the Node.js project with Mongoose and MongoDB.

Now that you have gotten this far, let’s amp up our game to push the data in the database on MONGODB Atlas:

How to connect to a MongoDB database in MongoDB Atlas, create a database, and then seed initial data:
Create a Node.js program. Call it any name you like:
Remember to use your own connection credentials for MONGO DB Atlas that we setup on Thursday:

const mongoose = require('mongoose');
// remember your models.js file that you made a while ago? Now make it available to this
// program with require
const { Book, Customer, Order } = require('./models');
// MongoDB Atlas connection URI const MONGODB_URI = 'your-mongodb-atlas-connection-uri';
// Connect to MongoDB Atlas database and seed initial data async function seedData() { try { // Establish MongoDB Atlas database connection await mongoose.connect(MONGODB_URI, { useNewUrlParser: true, useUnifiedTopology: true });
// Create 5 book records const books = await Book.create([ { title: 'Book 1', author: 'Author 1' }, { title: 'Book 2', author: 'Author 2' }, { title: 'Book 3', author: 'Author 3' }, { title: 'Book 4', author: 'Author 4' }, { title: 'Book 5', author: 'Author 5' } ]);
// Create 5 customer records const customers = await Customer.create([ { name: 'Customer 1', email: 'customer1@example.com' }, { name: 'Customer 2', email: 'customer2@example.com' }, { name: 'Customer 3', email: 'customer3@example.com' }, { name: 'Customer 4', email: 'customer4@example.com' }, { name: 'Customer 5', email: 'customer5@example.com' } ]);
// Create 3 order records const orders = await Order.create([ { customer: customers[0]._id, books: [books[0]._id, books[1]._id] }, { customer: customers[1]._id, books: [books[2]._id, books[3]._id] }, { customer: customers[2]._id, books: [books[4]._id, books[1]._id] } ]);
console.log('Seed data created successfully'); } catch (error) { console.error('Error seeding data:', error); } finally { // Close the database connection mongoose.connection.close(); } }
// Call the seedData function to seed initial data seedData();
In this modified version, the MONGODB_URI variable holds the connection URI obtained from MongoDB Atlas. The mongoose.connect method is used to connect to the MongoDB Atlas database by passing the MONGODB_URI and database connection options.
This code demonstrates how to establish a connection to a MongoDB database hosted on MongoDB Atlas and then seed initial data into that database using Mongoose.
Remember to replace 'your-mongodb-atlas-connection-uri' with the actual connection URI provided by MongoDB Atlas.

Remember to keep track of the names of your database, schema, and data objects.

Below is a stand-alone Node.js program that uses Mongoose to display all the collections and their respective data records in the MongoDB database:

javascript
// displayCollectionsData.js const mongoose = require('mongoose'); const { Book, Customer, Order } = require('./models');
// Establish a connection to the MongoDB database
// replace this line with the connection credentials for mongo db Atlas:
mongoose.connect('mongodb://localhost:27017/bookstore', { useNewUrlParser: true, useUnifiedTopology: true });
// Function to display all collections and their records async function displayCollectionsData() { try { // Fetch all book records const books = await Book.find().exec(); console.log('Books collection:'); console.log(books);
// Fetch all customer records const customers = await Customer.find().exec(); console.log('Customers collection:'); console.log(customers);
// Fetch all order records const orders = await Order.find().populate('customer').populate('books').exec(); console.log('Orders collection:'); console.log(orders); } catch (error) { console.error('Error fetching data:', error); } finally { // Close the connection mongoose.connection.close(); } }
// Call displayCollectionsData function displayCollectionsData();
In this stand-alone Node.js program, we first establish a connection to the MongoDB database using mongoose.connect. We then define a function displayCollectionsData to fetch and log all the records from the books, customers, and orders collections.
We use Mongoose methods like find and populate to retrieve the records and their referenced data.
After running this program using Node.js, it will display all the collections and their respective data records as per the structure and content stored in the MongoDB database.

We have created the seed.js and models.js files.

These files are commonly found in a Node.js application that uses Mongoose as the ODM (Object Data Modeling) library for MongoDB.

seed.js: This file contains the code for seeding initial data into the MongoDB database. It utilizes the Mongoose models defined in models.js to create and store sample records for books, customers, and orders in the database.
models.js: This file contains the Mongoose schema definitions for the data entities (e.g., books, users) and creates the corresponding models. These models act as interfaces for interacting with the MongoDB collections in a structured manner.

Wrapping up the Database construction part of it:

Here are the complete and completely working example codes for seed.js and models.js, along with an explanation of where the database is being created:

// file named : models.js

const mongoose = require('mongoose');
// Define Book schema const bookSchema = new mongoose.Schema({ title: { type: String, required: true }, author: { type: String, required: true } // Additional book properties can be added here });
// Create Book model const Book = mongoose.model('Book', bookSchema);
module.exports = { Book }; In this example, models.js defines a Mongoose schema for the Book entity and creates a corresponding model using mongoose.model. The Book model is then exported using module.exports to make it accessible to other files.

// file named : seed.js
const mongoose = require('mongoose'); const { Book } = require('./models');
// Connect to MongoDB database mongoose.connect('mongodb://localhost:27017/your-database-name', { useNewUrlParser: true, useUnifiedTopology: true });
// Function to seed initial data async function seedData() { try { // Create 5 book records const books = await Book.create([ { title: 'Book 1', author: 'Author 1' }, { title: 'Book 2', author: 'Author 2' }, { title: 'Book 3', author: 'Author 3' }, { title: 'Book 4', author: 'Author 4' }, { title: 'Book 5', author: 'Author 5' } ]);
console.log('Seed data created successfully'); } catch (error) { console.error('Error seeding data:', error); } finally { // Close the database connection mongoose.connection.close(); } }
// Call the seedData function seedData();


Here, seed.js connects to the MongoDB database using mongoose.connect and then defines the seedData function to create sample book records using the Book model from models.js. Once the seeding is complete, the database connection is closed.
The database is being created and connected to when the mongoose.connect method is called in seed.js with the connection string ('mongodb://localhost:27017/your-database-name') specifying the database name. This connects to a MongoDB server running on localhost on the default port (27017) and creates/accesses the database specified in the connection string.
Lastly, ensure to replace 'mongodb://localhost:27017/your-database-name' with the appropriate connection string for your MongoDB database.
This code provides a complete and functional example for seeding initial data into a MongoDB database using Mongoose and Node.js.


Now you have make a database, and populated it, and used 2 methods to verify that your data is in the database in MONGO DB REALM. You used DB Compass and a MONGOOSE SCRIPT to do this verification.
You are now very confident in your ability to use the API METHODS of MONGOOSE, and in your ability to work with JSON as a data structuring mechanism!
image.png

Lab Workbook Part 2: You will now front end your MONGO Database with an Express.js Webserver and HTML Page interface:


Version 1 of our Front End HTML:

(This retrieves the database contents but does not yet display it to the BOM)

Node.js program using Express.js to display all the books in the database:

// app.js import express from 'express'; import mongoose from 'mongoose'; import { Book } from './models';
const app = express();
// Establish a connection to the MongoDB database mongoose.connect('mongodb://localhost:27017/bookstore', { useNewUrlParser: true, useUnifiedTopology: true });
// Route to display all books
app.get('/books', async (req, res) => {
try { const books = await Book.find().exec(); res.json(books); } catch (error) { res.status(500).json({ error: 'Error fetching books' }); } });
// Start the server const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log(`Server is running on port ${PORT}`); });
In this Node.js program:
We use import to import the necessary modules and express constructs such as async and await.
The Express app initializes and sets up a route to fetch all the books from the database using a GET request to '/books'.
The database query is wrapped in a try/catch block to handle any errors that may occur during the asynchronous operation. When books are successfully fetched, they are sent back as JSON using res.json. In case of an error, a 500 status code and an error message are sent to the client.

Explainer:

In the context of an Express.js application, a route refers to a mapping between an HTTP request method (GET, POST, PUT, DELETE, etc.) and a specific endpoint (URL) on the server, along with a function (or handler) that should be executed when that endpoint is accessed.

In the provided Node.js program, the following route is defined:

// Route to display all books app.get('/books', async (req, res) => { try { const books = await Book.find().exec(); res.json(books); } catch (error) { res.status(500).json({ error: 'Error fetching books' }); } });
Here's a breakdown of the components of this route:
app.get('/books', async (req, res) => { ... }):
This line creates a route using the app object (representing the Express application) and specifies that it should respond to HTTP GET requests to the '/books' endpoint.
async (req, res) => { ... }:
This part is an arrow function that serves as the route handler. It takes two parameters: req (the request object) and res (the response object). When a request is made to the '/books' endpoint, this function will be executed to handle the request.
try { ... } catch (error) { ... }:
Inside the route handler function, there's a try/catch block.
The try block contains the logic for fetching all the books from the database using await Book.find().exec();.
If an error occurs during this asynchronous operation, it will be caught in the catch block.
res.json(books):
If the books are successfully fetched, they are sent back as a JSON response to the client.
This means that when a user accesses the '/books' endpoint, they will receive a JSON array containing all the books.
text
res.status(500).json({ error: 'Error fetching books' }) : If an error occurs, the server responds with a 500 status code and sends a JSON object with an error message.
In summary, the app.get('/books', ...) function creates a route that listens for GET requests to the '/books' endpoint. When such a request is made, the provided handler function is executed, which, in this case, fetches the books from the database and sends them back as a JSON response.


Version 2 of our Front End HTML:

To expand the provided Express.js program to display all the database records in the browser object model webpage when the user clicks a button, we can create a simple HTML page that includes a button to trigger the request and JavaScript code to handle the button click event and display the fetched data. Below is the expansion of the program:

Front End HTML html
<!-- index.html --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Bookstore</title> </head> <body> <h1>List of Books</h1> <ul id="bookList"></ul> <button id="fetchBooksBtn">Fetch Books</button>
<script> document.getElementById('fetchBooksBtn').addEventListener('click', async () => { try { const response = await fetch('/books'); const books = await response.json(); const bookList = document.getElementById('bookList'); bookList.innerHTML = ''; // Clear existing content
books.forEach(book => { const li = document.createElement('li'); li.textContent = `${book.title} by ${book.author}`; bookList.appendChild(li); }); } catch (error) { console.error('Error fetching and displaying books:', error); } }); </script> </body> </html>

Explanation:
The HTML file includes a button with the id fetchBooksBtn and an unordered list with the id bookList where the fetched book records will be displayed.
The JavaScript code listens for a click event on the "Fetch Books" button and executes an asynchronous function when the button is clicked.
Inside the event listener, a fetch request is made to the '/books' endpoint, and the response is processed as JSON.
Upon receiving the book data, the list is cleared and new list items are created and appended to the unordered list for each book retrieved from the server.
When the user clicks the "Fetch Books" button, the JavaScript code initiates a request to the server to fetch the book records, and upon successful retrieval, it dynamically updates the browser's DOM to display the book list.
This expansion in the form of a front-end HTML file integrates with the existing Node.js program to create a complete solution that displays the database records in the browser upon user interaction.

***** All the provided code honors ECMAScript 6 (ES6) best practices as specified.
Async/Await for Making Mongoose Calls: The code uses async/await for making Mongoose calls. Both the database connection setup and the GET request to fetch all books from the database use async/await for handling asynchronous operations.
Await Statements Wrapped in Try-Catch: The await statements are wrapped in try/catch blocks to handle any potential errors that may occur during the asynchronous operations. This ensures that errors are properly caught and handled.
Arrow Function Syntax: The code incorporates arrow function syntax throughout, including the route callback function and the button click event listener in the front-end HTML. Arrow functions are used in accordance with ES6 best practices for concise and clear function definitions.
In summary, the provided code fully conforms to the specified ECMAScript 6 best practices, showcasing the usage of async/await, try/catch blocks for error handling, and arrow function syntax.


Let's expand the vision by creating an index.html file that includes HTML forms to interact with the database to read and write records.

In this demonstration, we'll create a simple interface to add a new book to the database and display the existing books.


Here's a sample index.html that demonstrates this functionality along with best practices formulated in ECMAScript 6:
html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Bookstore</title> </head>
<body>
<h1>Bookstore</h1>
<h2>Add a New Book</h2> <form id="addBookForm"> <label for="title">Title:</label> <input type="text" id="title" name="title" required><br>
<label for="author">Author:</label> <input type="text" id="author" name="author" required><br>
<button type="submit">Add Book</button> </form>
<h2>List of Books</h2> <ul id="bookList"></ul>
<script> document.getElementById('addBookForm').addEventListener('submit', async (event) => { event.preventDefault(); // Prevent default form submission
const title = document.getElementById('title').value; const author = document.getElementById('author').value;
try { const response = await fetch('/books', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title, author }) }); const newBook = await response.json();
const bookList = document.getElementById('bookList'); const li = document.createElement('li'); li.textContent = `${newBook.title} by ${newBook.author}`; bookList.appendChild(li);
document.getElementById('addBookForm').reset();
// Clear the form fields after successful addition
} catch (error) { console.error('Error adding book:', error); } });

// Initial fetch of books when the page loads
async function fetchAndDisplayBooks() {
try { const response = await fetch('/books'); const books = await response.json(); const bookList = document.getElementById('bookList'); books.forEach(book => { const li = document.createElement('li'); li.textContent = `${book.title} by ${book.author}`; bookList.appendChild(li); }); } catch (error) { console.error('Error fetching and displaying books:', error); } }
// Call the function to fetch and display books when the page loads fetchAndDisplayBooks(); </script> </body> </html>

Explanation:
The HTML file includes a form for adding a new book and an unordered list to display the existing books.
The JavaScript code listens for the form submission event, prevents the default form submission, and then makes an asynchronous fetch request to add the new book to the database.
Upon successful addition of the new book, the list is updated to display the added book, and the form fields are cleared.
There's also an asynchronous function to fetch and display the existing books when the page loads.
This index.html file adheres to ECMAScript 6 best practices by utilizing async/await for making asynchronous requests, using arrow functions for event listeners, and wrapping await statements in try/catch blocks for error handling.
This demonstration provides a simple and interactive way to read and write records in the database using HTML forms. If you have further requirements or questions, feel free to ask!

Explain how this code connects the html bom to the mongo db:

const response = await fetch('/books', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title, author }) }); const newBook = await response.json();
The provided code snippet connects the HTML front end to the MongoDB back end in the following manner:
Fetching Data From the HTML to MongoDB:
When a user submits the form to add a new book, the JavaScript code captures the values for the title and author from the form fields using document.getElementById('title').value and document.getElementById('author').value.
Performing a POST Request:
The code sends a POST request to the '/books' endpoint using the fetch API. The endpoint is responsible for adding a new book to the database.
Defining Request Headers:
The POST request is configured with the 'Content-Type' header set to 'application/json'.
This indicates that the request body will contain JSON-formatted data.
Sending JSON-Formatted Data:
The fetch request includes a body property that contains the JSON representation of the title and author, created using JSON.stringify({ title, author }). This sends the title and author information to the server in a JSON format.
Processing the Server Response:
The response from the server is awaited using await response.json().
This converts the response body to a JSON object.
The resulting JSON object represents the newly added book in the database.
In summary, this code snippet forms a POST request that connects the HTML front end to the MongoDB back end by sending a JSON-formatted payload containing the new book's title and author information.
Upon receiving a response from the server, the code processes the JSON response, which represents the newly added book in the database.
This connection allows the HTML form to communicate with the MongoDB database, enabling the addition of new records.


Extended concepts:

Completing the CRUD workflow.
Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
CtrlP
) instead.