Two Model CRUD App - No Relationship - First Model
Lesson Objectives
- Init Directory
- Start express
- Create Home page
- Create Authors Index
- Create Authors New Page
- Set up Author Model
- Create Authors
POSTRoute - Show Authors on Index Page
- Create Authors Show Page
- Create Authors DELETE Route
- Create Authors Edit Page
- Create Authors PUT Route
Init Directory
mkdir blogcd blogtouch server.jsnpm init -ynpm install express
Start express
Let's start with some boilerplate code inside of server.js:
const express = require('express');
const app = express();
app.listen(3000, () => {
console.log('listening....');
});Create Home page
npm install ejsmkdir viewstouch views/index.ejs
Inside of views/index.ejs:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Express Blog</title>
</head>
<body>
<header>
<h1>Welcome to the Blog</h1>
<nav>
<ul>
<li>
<a href="/authors">Authors</a>
</li>
<li>
<a href="/articles">Articles</a>
</li>
</ul>
</nav>
</header>
</body>
</html>Inside of server.js:
app.get('/', (req, res) => {
res.render('index.ejs');
});Create Authors Index
mkdir views/authorstouch views/authors/index.ejs
Inside of views/authors/index.ejs:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Express Blog</title>
</head>
<body>
<header>
<h1>Authors</h1>
<nav>
<ul>
<li>
<a href="/">Home</a>
</li>
<li>
<a href="/authors/new">Create a new Author</a>
</li>
</ul>
</nav>
</header>
</body>
</html>mkdir controllerstouch controllers/authors.js
Inside of controllers/authors.js:
const express = require('express');
const router = express.Router();
router.get('/', (req, res) => {
res.render('authors/index.ejs');
});
module.exports = router;Use the controller in server.js:
const authorsController = require('./controllers/authors.js');
app.use('/authors', authorsController);Create Authors New Page
First wetouch views/authors/new.ejs.
Then we can add the following markup:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Express Blog</title>
</head>
<body>
<header>
<h1>Create an Author</h1>
<nav>
<ul>
<li>
<a href="/">Home</a>
</li>
<li>
<a href="/authors">Authors Index</a>
</li>
</ul>
</nav>
</header>
<main>
<form action="/authors" method="POST">
<input type="text" name="name" />
<input type="submit" value="Create Author" />
</form>
</main>
</body>
</html>Add the create route in controllers/authors.js:
router.get('/new', (req, res) => {
res.render('authors/new.ejs');
});Connect to MongoDB
npm install mongoose dotenvtouch .env- Connect in
server.js
Add ENV Variables
Inside of .env:
DATABASE_URL=mongodb+srv://<username>:<password>@general-assembly.1wjse.mongodb.net/meen-auth-starter?retryWrites=true&w=majority- Remember to use your own
DATABASE_URL. Copying the one above will not work.
Configure the Database
Don't forget to include this at the top of server.js:
require('dotenv').config();Then add this below, also in server.js:
// Dependencies
const mongoose = require('mongoose');
// Database Configuration
mongoose.connect(process.env.DATABASE_URL, {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false,
useCreateIndex: true,
});
// Database Connection Error / Success
const db = mongoose.connection;
db.on('error', (err) => console.log(err.message + ' is mongod not running?'));
db.on('connected', () => console.log('mongo connected'));
db.on('disconnected', () => console.log('mongo disconnected'));STOP! Check your work.
Boot up your server with nodemon and make sure you should see:
Listening ...
mongo connectedSet up Author Model
mkdir modelstouch models/authors.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const authorSchema = new Schema({
name: String
}, {
timestamps: true
});
const Author = mongoose.model('Author', authorSchema);
module.exports = Author;Create Authors Create Route
Use body parser inside of server.js:
app.use(express.urlencoded({ extended: false }));Inside of controllers/authors.js, let's require the Author model and define a create controller:
const Author = require('../models/authors.js');
//...
//...farther down the page
router.post('/', (req, res) => {
Author.create(req.body, (err, createdAuthor) => {
res.redirect('/authors');
});
});Show Authors on Index Page
Inside of controllers/authors.js, we'll refactor the index controller:
router.get('/', (req, res) => {
Author.find({}, (err, foundAuthors) => {
res.render('authors/index.ejs', {
authors: foundAuthors
});
})
});Now we can index the authors inside ofviews/authors/index.ejs:
<main>
<h2>List of Authors</h2>
<ul>
<% for(let i = 0; i < authors.length; i++){ %>
<li>
<a href="/authors/<%= authors[i]._id %>"><%= authors[i].name %></a>
</li>
<% } %>
</ul>
</main>Create Authors Show Page
Create the file withtouch views/authors/show.ejs, and add this markup to it:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Express Blog</title>
</head>
<body>
<header>
<h1>Show Page for <%= author.name %></h1>
<nav>
<ul>
<li>
<a href="/">Home</a>
</li>
<li>
<a href="/authors">Author Index</a>
</li>
</ul>
</nav>
</header>
<main>
<section>
<h2>Author Attributes:</h2>
<ul>
<li>Name: <%= author.name %></li>
</ul>
</section>
</main>
</body>
</html>Toward the bottom controllers/authors.js, we'll add a show controller:
//avoid this handling /new by placing it towards the bottom of the file
router.get('/:id', (req, res) => {
Author.findById(req.params.id, (err, foundAuthor) => {
res.render('authors/show.ejs', {
author: foundAuthor
});
});
});Create Authors DELETE Route
npm install method-override- Use
method-overrideinserver.js:
const methodOverride = require('method-override');
app.use(methodOverride('_method'));Inside of controllers/authors.js, we'll define our delete controller:
router.delete('/:id', (req, res) => {
Author.findByIdAndRemove(req.params.id, () => {
res.redirect('/authors');
});
});Let's make sure to use the _method URL param to make the delete button work in views/authors/show.ejs:
<section>
<form action="/authors/<%= author._id %>?_method=DELETE" method="POST">
<input type="submit" value="Delete Author" />
</form>
</section>Create Authors Edit Page
Create a link inside ofviews/authors/show.ejs:
<section>
<a href="/authors/<%= author._id %>/edit">Edit</a>
</section>Let's define the edit controller inside of controllers/authors.js like this:
router.get('/:id/edit', (req, res) => {
Author.findById(req.params.id, (err, foundAuthor) => {
res.render('authors/edit.ejs', {
author: foundAuthor
});
});
});Next, we'll create an edit page with touch views/authors/edit.ejs, and add this markup to it:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Express Blog</title>
</head>
<body>
<header>
<h1>Edit <%= author.name %>'s Info</h1>
<nav>
<ul>
<li>
<a href="/">Home</a>
</li>
<li>
<a href="/authors">Authors Index</a>
</li>
</ul>
</nav>
</header>
<main>
<h2>Author Attributes:</h2>
<form action="/authors/<%= author._id %>?_method=PUT" method="POST">
<input type="text" name="name" value="<%= author.name %>" /><br />
<input type="submit" value="Update Author" />
</form>
</main>
</body>
</html>Create Authors PUT Route
Now we just need to define our update controller inside of controllers/authors.js:
router.put('/:id', (req, res) => {
Author.findByIdAndUpdate(req.params.id, req.body, () => {
res.redirect('/authors');
});
});