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
POST
Route - Show Authors on Index Page
- Create Authors Show Page
- Create Authors DELETE Route
- Create Authors Edit Page
- Create Authors PUT Route
Init Directory
mkdir blog
cd blog
touch server.js
npm init -y
npm 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 ejs
mkdir views
touch 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/authors
touch 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 controllers
touch 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 dotenv
touch .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 connected
Set up Author Model
mkdir models
touch 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-override
inserver.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');
});
});