SEI-Example
  • Introduction
  • About These Notes
  • Syllabus
  • Development Workflow
    • Installfest
      • Mac OSX
      • Linux
      • Git Configuration
      • Sublime Packages
    • Command Line
      • The Terminal
      • Filesystem Navigation
      • File Manipulation
      • Additional Topics
    • Intro to Git
      • Version Control
      • Local Git
      • Remote Git
      • Git Recipes
    • Group Collaboration
      • Git Workflows
      • Project Roles and Tools
    • VS Code Tips & Tricks
  • HTML/CSS
    • HTML
    • CSS Selectors
    • CSS Box Model and Positioning
      • Box Model
      • Display and Positioning
      • Flexbox
      • Grid
      • Flexbox & Grid Games
      • Floats and Clears
      • Additional Topics
    • Advanced CSS
      • Responsive Design
      • Pseudo-Classes/Elements
      • Vendor Prefixes
      • Custom Properties
      • Additional Topics
    • Bootstrap
    • CSS Frameworks
    • Accessibility
  • JavaScript
    • Primitives
    • Arrays
    • Objects
    • Control Flow
      • Boolean Expressions
      • Conditionals
      • Loops
      • Promises
    • Functions
      • Callbacks
      • Timing Functions
      • Iterators
    • DOM and Events
    • DOM Manipulation
    • HTML5 Canvas
    • How To Reduce Redundancy
    • (2019) JavaScript OOP
    • (2016) OOP with Classes
    • (1995) OOP with Prototypes
      • Constructors
      • Prototypes
    • Intro to TDD
    • Scoping
    • Inheritance
      • Prototypal Inheritance
      • Call, Apply, and other Functions
      • ES6 Inheritance
      • Resources
    • Custom Node Modules
    • Additional Topics
      • AJAX, Fetch, and Async/Await
      • AJAX w/JSON and Localstorage
        • AJAX w/JSON
        • Local Storage
      • Async module
      • Data Scraping
  • jQuery
    • Intro
      • DOM Manipulation
      • Reddit Practice
      • Styling
      • Events
    • Plugins
    • AJAX
  • APIs
    • Fetch
    • AJAX w/jQuery
    • AJAX w/Fetch
  • Databases
    • Intro to SQL
    • Advanced SQL
    • MongoDB
      • Intro to NoSQL
      • CRUD in MongoDB
      • Data Modeling
      • Intermediate Mongo
  • Node/Express
    • Node
      • Intro to Node
      • Node Modules
      • Node Package Manager (NPM)
    • Express
      • Intro to Express
        • Routes
        • Views
        • Templates
        • Layouts and Controllers
        • CRUD & REST
          • Get and Post
          • Put and Delete
      • APIs with Express (request)
      • APIs with Express (axios)
    • Sequelize
      • Terminology
      • Setup
      • Using Models
      • Seeding Data
      • Validations and Migrations
      • Resources
      • 1:M Relationships
      • N:M Relationships
    • Express Authentication
      • Research Components
      • Code Components
      • Auth in Theory
        • Sessions
        • Passwords
        • Middleware
        • Hooks
      • Auth in Practice
        • Create the User
        • User Signup
        • Sessions
        • User Login
        • Authorization and Flash messages
    • Testing with Mocha and Chai
    • Mongoose
      • Mongoose Associations
    • JSON Web Tokens
      • Codealong
    • Additional Topics
      • oAuth
      • Geocoding with Mapbox
      • Geocoding and Google Maps
      • Cloudinary
      • Websockets with Socket.io
      • SASS
  • Ruby
    • Intro to Ruby
    • Ruby Exercises
    • Ruby Classes
    • Ruby Testing with Rspec
    • Ruby Inheritance
    • Ruby Data Scraping
  • Ruby on Rails
    • Intro to Rails
    • APIs with Rails
    • Asset Pipeline
    • Rails Auth and 1-M
      • Auth Components
    • Rails N:M
    • ActiveRecord Polymorphism
    • Additional Topics
      • oAuth
      • SASS
      • Rails Mailers
      • Cloudinary
      • Jekyll
  • React (Updated 2019)
    • ES6+/ESNext
      • Const and Let
      • Arrow Functions
      • Object Literals and String Interpolation
      • ES6 Recap
      • ES6 Activity
    • Intro to React
      • Create React App
      • Components and JSX
      • Virtual DOM
      • Props
      • Dino Blog Activity
      • Nested Components
      • Lab: LotR
    • React State
      • Code-Along: Mood Points
      • Code-Along: Edit Dino Blog
      • Lab: Simple Calc
      • Lifting State
    • React Router
      • Browser History/SPAs
      • React Router (lesson and full codealong)
      • Router Lab
    • Fetch and APIs
      • APIs with Fetch and Axios
      • Fetch the Weather
    • React Hooks
    • React LifeCycle
      • Lab: Component LifeCycle
    • React Deployment
    • Additional Topics
      • React Frameworks
        • Material UI Theming
      • Typescript
        • More Types and Syntax
        • Tsconfig and Declaration Files
        • Generics with Linked List
      • Redux
      • TypeScript
      • Context API
      • React Native
  • Meteor
  • Deployment and Config
    • Deploy - Github Pages
    • Deploy - Node/Sequelize
    • Deploy - Node/MongoDB
    • Deploy React
    • Deploy - Rails
      • Foreman (Environment Variables)
    • Deploy - AWS Elastic Beanstalk
    • Deploy - S3 Static Sites
    • Deploy - Django
    • Deploy - Flask
  • Data Structures and Algorithms
    • Recursion
    • Problem Solving - Array Flatten
    • Binary Search
    • Algorithm Complexity
    • Stacks and Queues
    • Bracket Matching
    • Ruby Linked Lists
      • Sample Code
      • Beginner Exercises
      • Advanced Exercises
    • JS Linked Lists
      • Sample Code
      • Beginner Exercises
      • Beginner Solutions
    • Hash Tables
    • Intro to Sorting
    • Insertion Sort
    • Bucket Sort
    • Bubble Sort
    • Merge Sort
    • Quick Sort
    • Heap Sort
    • Sorting Wrapup
    • Hashmaps
    • Trees and Other Topics
  • Python
    • Python Installation
    • Intro to Python
    • Python Lists
    • Python Loops
    • Python Dictionaries
    • Python Sets and Tuples
    • Python Cheatsheet
    • Python Functions
    • Python Classes
    • Python Class Inheritance
    • Intro to Flask
    • Intro to SQLAlchemy
      • Flask and SQLAlchemy
    • Using PyMongo
    • Intro to Django
    • CatCollector CodeAlong
      • URLs, Views, Templates
      • Models, Migrations
      • Model Form CRUD
      • One-to-Many Relations
      • Many-to-Many Relations
      • Django Auth
    • Django Cheatsheet
    • Django Auth
    • Django Polls App Tutorial
    • Django School Tool Tutorial
    • Django 1:M Relationships
    • Custom Admin Views
    • Data Structures and Algorithms
      • Recursion
      • Binary Search
      • Stacks and Queues
      • Linked Lists
      • Binary Trees
      • Bubble Sort
      • TensorFlow & Neural Networks
    • Adjacent Topics
      • Raspberry Pi
      • Scripting
  • Assorted Topics
    • History of Computer Science
    • Regular Expressions
    • Intro to WDI (Course Info)
    • Being Successful in WDI
    • Internet Fundamentals
      • Internet Lab
    • User Stories and Wireframing
      • Wireframing Exercise: Build an Idea
    • Post WDI
      • Learning Resources
      • Deliverables -> Portfolio
      • FAQ
  • Projects
    • Project 1
    • Project 2
    • Project 3
      • Project 3 Pitch Guidelines
    • Project 4
    • Past Projects
      • Project 1
      • Project 2
      • Project 3
      • Project 4
      • Portfolios
    • Post Project 2
    • MEAN Hackathon
      • Part 1: APIs
      • Part 2: Angular
    • Portfolio
  • Web Development Trends
  • Resources
    • APIs and Data
    • Tech Websites
    • PostgreSQL Cheat Sheet
    • Sequelize Cheat Sheet
    • Database Administration
  • Archived Section
    • (Archived) ReactJS
      • Intro to React
        • Todo List Codealong
        • Additional Topics
      • Deploy React
      • React with Gulp and Browserify
        • Setting up Gulp
        • Additional Gulp Tasks
      • React Router
        • OMDB Router
        • OMDB Search
        • Additional Resources
      • React Animations
        • CSS Animations
    • AngularJS
      • Intro to AngularJS
        • Components and SPA
        • Create an Angular App
      • Angular Directives and Filters
      • Angular Animation
      • Angular Bootstrap Directives
        • Bootstrap Modals
      • Angular $http
      • Angular Services
        • Service Recipes
        • ngResource
        • Star Wars Codealong
      • Angular Routing
      • Angular + Express
      • Angular Authentication
        • Additional Topics
      • Angular Components
      • Angular Custom Filters
      • Angular Custom Directives
Powered by GitBook
On this page
  • Objectives
  • 1. Set up a new express app called crud_dinosaurs.
  • 2. Index / Read (GET) route
  • 3. Show / Read (GET) route
  • 4. New / Read (GET) route
  • 5. Create (POST) route
  • Show / Read (GET) with a Form
  1. Node/Express
  2. Express
  3. Intro to Express
  4. CRUD & REST

Get and Post

So far, we've only been rendering views, which is why we've been using GET for all of our routes. Now that we're working with data, we'll start to see how the other HTTP verbs come into play. Here we will focus on GET and POST.

Objectives

  • Implement GET and POST routes in express.

1. Set up a new express app called crud_dinosaurs.

Incorporate express-ejs-layouts.

Backend data store

We'll start workign with data from an actual database soon, but for now we'll just focus on routes and use, a JSON object as our data store. In the root of the project, create a dinosaurs.json file with the following contents:

[
  {
    "name":"Littlefoot",
    "type":"apatosaurus"
  },
  {
    "name":"Cera",
    "type":"triceratops"
  },
  {
    "name":"Ducky",
    "type":"saurolophus"
  },
  {
    "name":"Petrie",
    "type":"pteranodon"
  },
  {
    "name":"Spike",
    "type":"stegosaurus"
  }
]

2. Index / Read (GET) route

Index is a route (URL) that lists all items of a specific type. It is a GET request to (in this example) /dinosaurs.

Format the ejs to display the data. Assume that we will pass the data in as myDinos.

Index view -- in /views/dinosaurs/index.ejs

<ul>
  <% myDinos.forEach(function(dino) { %>
  <li><%= dino.name %> is a <%= dino.type %></li>
  <% }); %>
</ul>

To access our data, we'll use the fs (filesystem) core module. Import this module in index.js

const fs = require('fs');

Now let's pull in our data and take a took at it.

// lists all dinosaurs
app.get('/dinosaurs', function(req, res) {
  const dinosaurs = fs.readFileSync('./dinosaurs.json');
  console.log(dinosaurs);
});

Note: This console.log() is in our server file, which means it will print to our terminal, NOT the browser inspector.

Try parsing the data before printing it:

// lists all dinosaurs
app.get('/dinosaurs', function(req, res) {
  const dinosaurs = fs.readFileSync('./dinosaurs.json');
  const dinoData = JSON.parse(dinosaurs);
  console.log(dinoData);
});

That's more like it! Now lets send it to our EJS file:

// lists all dinosaurs
app.get('/dinosaurs', function(req, res) {
  const dinosaurs = fs.readFileSync('./dinosaurs.json');
  const dinoData = JSON.parse(dinosaurs);
  res.render('dinosaurs/index', {myDinos: dinoData});
});

In the above example we load the dinosaurs/index.ejs view and pass it dinoData as mydinosaurs. Now we can access myDinos directly in the index.ejs file.

3. Show / Read (GET) route

Show is a route that displays a single item of a specific type. Since we're still just reading data, it is a GET request to (in this example) /dinosaurs/1

Create a dinosaurs/show.ejs file:

<%= myDino.name %> is a <%= myDino.type %>.

Now let's write our show route. We can access the index from the url through the req.params object, but it will be a string. In order to use in to access an array value, we need to cast it to an integer.

Show route -- in index.js

//express show route for dinosaurs (lists one dinosaur)
app.get('/dinosaurs/:idx', function(req, res) {
  // get dinosaurs
  const dinosaurs = fs.readFileSync('./dinosaurs.json');
  const dinoData = JSON.parse(dinosaurs);

  //get array index from url parameter
  const dinoIndex = parseInt(req.params.idx);

  //render page with data of the specified animal
  res.render('dinosaurs/show', {myDino: dinoData[dinoIndex]});
});

In the above example we load the dinosaurs/show.ejs view and pass it a specific item from the dinoData array as myDino. We use the :idx url parameter to specify which animal to display. This means in the show.ejs file we can access myDino directly.

4. New / Read (GET) route

Form tags have two attributes that are very import for their CRUD functionality:

  • action: This value should be a path. Specifically, it is the url pattern associated with the route that will handle the data - in this case, that will be the /dinosaurs POST route we will write.

Create a dinosaurs/new.ejs view that contains an html form:

<form method="POST" action="/dinosaurs">
  <label for="dinosaurType">Type</label>
  <input id="dinosaurType" type="text" name="type">

  <label for="dinosaurName">Name</label>
  <input id="dinosaurName" type="text" name="name">

  <input type="submit">
</form>

Now write a GET route so we can view this form at localhost:3000/dinosaurs/new:

app.get('/dinosaurs/new', function(req, res){
  res.render('dinosaurs/new');
});

Not working? Make sure this route is above the show (/dinosaurs/:idx) route, otherwise the show route will catch the request and pass in "new" as req.params.idx.

5. Create (POST) route

This middleware will store the data submitted from the form in a user-friendly req.body object.

index.js

const express = require('express');
const app = express();
const ejsLayouts = require('express-ejs-layouts');
const fs = require('fs');

app.set('view engine', 'ejs');
app.use(ejsLayouts);
//body-parser middleware
app.use(express.urlencoded({extended: false}));

.
.
.

Now, if we can access the form data in a POST route!

index.js

app.post('/dinosaurs', function(req, res) {
  console.log(req.body);
});

Try adding a new dinosaur and make sure you see the appropriate data come through in the terminal when you submit the form.

body-parser Summary: Form data is passed as payload of the request. Every field that has a name will be included in that payload and it is sent as form encoded text. When body-parser is used, it automatically parses the form body into a javascript object that we can use and it stores it in req.body so we can use it (similar to how we convert API responses to JSON. All of this is done as middleware, which we just configured.

The name attribute matters! In the above example we could access the dinosaur type form field by using req.body.type and the name field by using req.body.name. This correlates directly to the names given to the form fields in the form html above.

Generally, the code in the express route would contain code that would CREATE an item in a database and redirect the user to a route with a confirmation message of some sort or just back to the index route. For this example we're going to use the JSON file created above to store our data. This will involve three steps:

  • Reading the JSON file

  • Pushing the new animal to the object

app.post('/dinosaurs', function(req, res) {
  // read dinosaurs file
  const dinosaurs = fs.readFileSync('./dinosaurs.json');
  dinosaurs = JSON.parse(dinosaurs);

  // add item to dinosaurs array
  dinosaurs.push(req.body);

  // save dinosaurs to the data.json file
  fs.writeFileSync('./dinosaurs.json', JSON.stringify(dinosaurs));

  //redirect to the GET /dinosaurs route (index)
  res.redirect('/dinosaurs');
});

JSON.stringify does the opposite of JSON.parse - it converts javascript data into json data.

Show / Read (GET) with a Form

There may be instances where you need to GET dinosaurs, but you don't want them all. A good example is filtering dinosaurs with a specific name via a search bar.

In these cases, you don't want to use a POST action, because POST is reserved for creating new resources. Instead, we can create another form with a GET method, and read the data via a querystring. This is an appropriate use of the GET form method because the user input is not sensitive.

Add a form to dinosaurs/index.ejs

<form method="GET" action="/dinosaurs">
  <label for="nameFilter">Filter by Name</label>
  <input id="nameFilter" type="text" name="nameFilter">
  <input type="submit">
</form>

The idea here is that the search bar allows the user to filter what's on the page, so it will be a GET request to /dinosaurs... but we already have a route for that! When you submit a form using the GET method, the key/value pairs are appended to the URL in a query string. Try searching for a dinosaur now and notice what happens to the URL. This query string, like parameters (req.params) is available via the request object. We'll use a conditional to check if there's a querystring, then filter the dinosaurs if one is present.

app.get('/dinosaurs', function(req, res) {
  const dinosaurs = fs.readFileSync('./dinosaurs.json');
  const dinoData = JSON.parse(dinosaurs);

  const nameFilter = req.query.nameFilter;

  if (nameFilter) {
    dinoData = dinoData.filter(function(dino) {
      return dino.name.toLowerCase() === nameFilter.toLowerCase();
    });
  }

  res.render('dinosaurs/index', {myDinos: dinoData});
});
PreviousCRUD & RESTNextPut and Delete

Last updated 3 years ago

That doesn't look very helpful, does it? That's because we're pulling in a JSON object, which isn't quite the same as a normal JS object. JSON (JavaScript Object Notation), is a standard format for data that is being transmitted (sent back and forth), and it needs to be parsed, or converted to a true JS data type - in this case, an array. Read more about working with JSON .

To create an item (dinosaur in this example) we need to get the data about that item, so we'll use a .

method: HTTP verb - GET or POST. You will use POST most often because it is significantly more secure. Read about the difference between these two methods by scrolling down to the "When to Use GET" AND "When to Use Post" sections of .

When the above form is submitted it will make a POST to the url /dinosaurs with the data contained in the form fields. To receive this data, we need to create the POST route and use some middleware to make the data readable. This middleware is new to express and prior to version 4, we had to manually install the body-parser node package in order to use it. (If it bothers you that we're glazing over how the data comes through before we send it through something like body-parser, read . It will always make sense to use some sort of framework like body-parser in practice, but if you're interested in capturing the raw data, see .)

The express.urlencoded() middleware tells body-parser to capture urlencoded data (form data) and store it in req.body. The {extended: false} option ensures that the values in this body will either be strings or arrays. More on this . Further discussion on it .

Writing the new JSON file using (this will replace the old dinosaurs.json)

here
form
this page
this article
this article
here
here
fs.writeFileSync