Two Model CRUD App - No relationship - Second Model




Lesson Objectives

  1. Create Articles Index
  2. Create Articles New Page
  3. Set up Article Model
  4. Create Articles POST Route
  5. Show Articles on Index Page
  6. Create Articles Show Page
  7. Create Articles DELETE Route
  8. Create Articles Edit Page
  9. Create Articles PUT Route



Create Articles Index

  1. mkdir views/articles
  2. touch views/articles/index.ejs

Add the markup below to views/articles.ejs:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>Express Blog</title>
	</head>
	<body>
		<header>
			<h1>Articles</h1>
			<nav>
				<ul>
					<li>
						<a href="/">Home</a>
					</li>
					<li>
						<a href="/articles/new">Create a new Article</a>
					</li>
				</ul>
			</nav>
		</header>
	</body>
</html>



  1. mkdir controllers
  2. touch controllers/articles.js

Inside controllers/articles.js, we'll define our first controller action:

const express = require('express');
const router = express.Router();

router.get('/', (req, res) => {
	res.render('articles/index.ejs');
});

module.exports = router;



Require and mount controller in server.js:

const articlesController = require('./controllers/articles.js');
app.use('/articles', articlesController);



Create Articles New Page

touch views/articles/new.ejs and add this markup below:

<!DOCTYPE html>
<html>

<head>
	<meta charset="utf-8">
	<title>Express Blog</title>
</head>

<body>
	<header>
		<h1>Create an Article</h1>
		<nav>
			<ul>
				<li>
					<a href="/">Home</a>
				</li>
				<li>
					<a href="/articles">Articles Index</a>
				</li>
			</ul>
		</nav>
	</header>
	<main>
		<form action="/articles" method="POST">
			<input type="text" name="title" /><br />
			<textarea name="body"></textarea><br />
			<input type="submit" value="Publish Article" />
		</form>
	</main>
</body>

</html>


Next, we'll define a create route in controllers/articles.js:

router.get('/new', (req, res) => {
	res.render('articles/new.ejs');
});



Set up Article Model

touch models/articles.js so we can define this model below:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const articleSchema = new Schema({
	title: String,
	body: String
});

const Article = mongoose.model('Article', articleSchema);

module.exports = Article;



Create Articles Create Route

Next, inside of controllers/articles.js, we'll require the Article model and define a create controller:

const Article = require('../models/articles.js');
//...
//...farther down the page
router.post('/', (req, res) => {
	Article.create(req.body, (err, createdArticle) => {
		res.redirect('/articles');
	});
});



Show Articles on Index Page

Let's define an index controller inside of controllers/articles.js:

router.get('/', (req, res) => {
	Article.find({}, (err, foundArticles) => {
		res.render('articles/index.ejs', {
			articles: foundArticles
		});
	});
});



Then we can show the articles inside of views/articles/index.ejs with this markup:

<main>
	<h2>List of Articles</h2>
	<ul>
		<% for(let i = 0; i < articles.length; i++){ %>
		<li>
			<a href="/articles/<%=articles[i]._id%>"><%= articles[i].title %></a>
		</li>
		<% } %>
	</ul>
</main>



Create Articles Show Page

touch views/articles/show.ejs and add this markup below:

<!DOCTYPE html>
<html>

<head>
	<meta charset="utf-8">
	<title>Express Blog</title>
</head>

<body>
	<header>
		<h1><%= article.title %></h1>
		<nav>
			<ul>
				<li>
					<a href="/">Home</a>
				</li>
				<li>
					<a href="/articles">Articles Index</a>
				</li>
			</ul>
		</nav>
	</header>
	<main>
		<section>
			<%= article.body %>
		</section>
	</main>
</body>

</html>



Towards the bottom controllers/articles.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) => {
	Article.findById(req.params.id, (err, foundArticle) => {
		res.render('articles/show.ejs', {
			article: foundArticle
		});
	});
});



Create Articles DELETE Route

Here's how we can define our DELETE controller inside of controllers/articles.js:

router.delete('/:id', (req, res) => {
	Article.findByIdAndRemove(req.params.id, () => {
		res.redirect('/articles');
	});
});



Now we just need to ensure our DELETE button is structured like this inside of views/articles/show.ejs:

<section>
	<form action="/articles/<%=article._id%>?_method=DELETE" method="POST">
		<input type="submit" value="Delete Article" />
	</form>
</section>



Create Articles Edit Page

Create a link on views/articles/show.ejs:

<section>
	<a href="/articles/<%=article._id%>/edit">Edit</a>
</section>



Here's how we can define our edit controller inside of controllers/articles.js:

router.get('/:id/edit', (req, res) => {
	Article.findById(req.params.id, (err, foundArticle) => {
		res.render('articles/edit.ejs', {
			article: foundArticle
		});
	});
});



Then we'll touch views/articles/edit.ejs and add the below markup for our edit page:

<!DOCTYPE html>
<html>

<head>
	<meta charset="utf-8">
	<title>Express Blog</title>
</head>

<body>
	<header>
		<h1>Edit <%= article.title %>'s Info</h1>
		<nav>
			<ul>
				<li>
					<a href="/">Home</a>
				</li>
				<li>
					<a href="/articles">Articles Index</a>
				</li>
			</ul>
		</nav>
	</header>
	<main>
		<h2>Article Attributes:</h2>
		<form action="/articles/<%= article._id %>?_method=PUT" method="POST">
			<input type="text" name="title" value="<%= article.title %>" /><br />
			<textarea name="body"><%= article.body %></textarea><br />
			<input type="submit" value="Update Article" />
		</form>
	</main>
</body>

</html>



Create Articles PUT Route

Finally, inside of controllers/articles.js, we'll define our update controller:

router.put('/:id', (req, res) => {
	Article.findByIdAndUpdate(req.params.id, req.body, () => {
		res.redirect('/articles');
	});
});