A Markdown Blog ( Node.js, Express, And MongoDB )
Published: 2024-04-11 18:29:29

31/3/24

##INTRODUCTION

Simple 

####Setup Server

1. At first  we will create our package.json file with default values by giving
        

                   npm init -y


**npm:** This is the Node Package Manager, a command-line tool used for managing Node.js packages and dependencies.

**init:** This is a command used to initialize a new Node.js project by creating a package.json file, which is a metadata file that contains information about the project, such as its name, version, description, dependencies, and more.

**-y:** This is a flag that stands for "yes." When used with npm init, it tells npm to automatically accept default values for all prompts and initialize the package.json file without requiring any user input.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xmg5ajww14ycbci7vp6x.png)



<hr>


 2 . Now we are going to add express mongoDB and js.


             npm i express mongoose ejs

The command npm i express mongoose ejs is used to install three Node.js packages: Express, Mongoose, and EJS.

Here's what each package does:

**Express:** Express is a fast, unopinionated, and minimalist web framework for Node.js. It provides a robust set of features for building web applications and APIs, including routing, middleware support, and template rendering.

**Mongoose:** Mongoose is an Object Data Modeling (ODM) library for MongoDB and Node.js. It provides a straightforward schema-based solution for modeling application data and interacting with MongoDB databases. Mongoose simplifies the process of defining schemas, validating data, and performing CRUD operations.

**EJS:** EJS (Embedded JavaScript) is a simple templating language that lets us generate HTML markup with plain JavaScript. It allows us to embed JavaScript code directly within our HTML templates, making it easy to create dynamic web pages by dynamically rendering data.

- Now we are going to add dev dependencies and nodemon(it will help us for refresh our webpage automatically);

           npm i --save-dev nodemon

to run nodemon we have to add 


       "devStart": "nodemon server.js"

in our package.json file.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/goirsj41al7ofrjge1sd.png)

and now we are going to create a server.js file and run 

                npm run devStart




---

####Create Index route


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2pglvvuhpdenqx483uq2.png)

      
      app.set('view engine', 'ejs');



Here, app.set is a method used to assign settings to our Express application. The 'view engine' setting is used to specify the template engine for your application.

'EJS' stands for Embedded JavaScript. It is a simple templating language/engine that lets us generate HTML markup with plain JavaScript.

1. Now we are going to create a views folder and create index.ejs file and write some basic html code and access it from server.js file using,
  
      res.render('index');



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/71tpjy21z73zhme7hcu0.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r0c14k1x1vumqoy5f08e.png)

---


####Creating Article Routes


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0q5mze1jqg89zfxi23yt.png)

in our project there will lots of routes like, show, edit, delete and more. We are not going to access them from our server.js file. So that we are going to create **routes** folder, in that we are going to create article.js.

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

module.exports = router ;
```


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/me2sow9ctz0f8oved9dm.png)


in server.js we can easily access article.js adding,

`const articleRouter = require('./routes/articles');`


`app.use(articleRouter);`
    

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/61nbjg8pijpm0ka0eazm.png)


we want `/article` in front of every routes file. So that we can use 
     
        app.use('/articles', articleRouter);


this will give **'/'** to the articles.js file when search `localhost:5000/articles` . And in articles.js we can easily catch it using,

articleRouter is an instance of an Express router. A router is a middleware that allows you to group and handle routing to different parts of your application in a modular way. This router will handle all requests that start with /articles.

```
router.get('/', (req, res) => {
    res.send('This is from article.js');
})
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nbjuquysf5c7cotjbw87.png)


---

####Pass Articles to Index

Currently we are passing only index but we want to pass all of our articles values. 

```
const articles = [{
        title: 'Test Article',
        createdAt: Date.now(),
        description: 'Test description'
    }]
    res.render('index', {articles: articles});
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/30kt421lgm1t97pna6qq.png)


we are going to pass articles value in index.ejs  later.

- Now we are going to add bootstrap link to index.ejs file.

     
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">



and add New Article button.

```
<div class="container">
        <h1 class="mb-4">Blog Articles</h1> <!-- mb-4 stands for margin bottom of 4. -->

        <a href="/articles/new" class="btn btn-success">New Article</a> <!-- btn-success will give green color in the button.-->
    </div>
```


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y81ln752s1yuzknp23yy.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/08g1gogczwntjdr72v36.png)


---

####Creating body

For body we are going to add a forEach method to index.ejs and make some change on server.js,


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pl9mkug4dcbsb2h6gmco.png)

- in **index.ejs** we are going to add ,

```
<div class="container">
        <h1 class="mb-4">Blog Articles</h1> <!-- mb-4 stands for margin bottom of 4. -->

        <a href="/articles/new" class="btn btn-success">New Article</a> <!-- btn-success will give green color in the button.-->

        <!-- for each will go through all the key value -->
        <% articles.forEach(article => {
            %>
            <div class="card mt-4"> <!-- Creating card-->
                <div class="card-body"> <!-- Card content-->
                    <h4 class="card-title"> <%= article.title %></h4>
                    <div class="card-subtitle text-muted mb-2">
                        <%= article.createdAt.toLocaleDateString() %>  <!-- this will create current date and the variable have to be new Date()-->
                    </div>

                    <!-- This is for text description-->
                    <div class="card-text mb-2">
                        <%= article.description %>
                    </div>
                </div>
            </div> 
            <%
        }) %>
    </div>
```


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/63fk6fx55wx06nrh1c3v.png)


- And in **server.js** we updated the articles createdAt value,

      createdAt: new Date(),



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gihy8vjw1peqelqioj9u.png)



####Creating new article Route

so in the beginning we created **New Article** button. Now we are going to create new route for it.

1. In article.js we updated the route.get,

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

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9w90wfxe7zojzh5hgxrk.png)

 2 . Now we create new folder in views, named **articles** and in that we create a new file name **new.ejs** and move the index.ejs file to articles folder.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1pjabpna0ckd9sentmr8.png)

 3 . we update the path in **server.js**,
    
      res.render('articles/index', {articles: articles});


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h9byi8fns46vk8swizrj.png)


 4 . In **new.ejs** we add,

```
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- bootstrap link -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
    
    <title>Blog</title>
</head>
<body>
    <div class="container">
        <h1 class="mb-4">New Article</h1>

        <form action="/articles" method="POST">
            
        </form>
    </div>
</body>
</html>
```

but this new page is not finish yet, we have to some more. We need to create a sample format that give us same interface for **New Article** input and for **Edit Article**. So we are going to create a new file name **_form_fields.ejs** in the folder, views->articles-> _form_fields.ejs. 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ep6cw92k6ull3croja78.png)

`<%-` this symbol helps use to render actual html, instead of text.

Now we are going to add this to our **new.ejs** file,

     <%- include('_form_fields') %>

by this we can access **_form_fields.ejs** and what ever we write in form file it show to our new article page.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2fp5nw7cgj61e5bxp6uu.png)

Now we write some demo,
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/thzxkm2dsylul4cihbfu.png)

and the output is, 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0de5qxb55xsa43xeaxxe.png)

Okey, now we are going to modify our form_fields file,

- So our edited file of _form_fields.ejs now is,

```
<!-- This is for title-->
<div class="form-group">
    <label for="title">Title</label>
    <input required type="text" name="title" id="title" class="form-control"> <!-- form-control gives us the nice form fromat and the required give us the constraint of must fullfill the form-->
</div>

<!-- This is for description-->
<div class="form-group">
    <label for="description">Description</label>
    <textarea name="description" id="description" class="form-control"></textarea><!-- form-control gives us the nice form fromat and the required give us the constraint of must fullfill the form-->
</div>

<!-- This is for markdown-->
<div class="form-group">
    <label for="markdown">Markdown</label>
    <textarea name="markdown" id="markdown" class="form-control"></textarea><!-- form-control gives us the nice form fromat and the required give us the constraint of must fullfill the form-->
</div>

<!--cancel btn which will cancel editing and take us to home page-->

<a href="/" class="btn btn-secondary">Cancel</a>

<!-- Submit button-->
<button type="submit" class="btn btn-primary">Save</button>
```

now this cancel btn will take us to home page and save btn will post the data to our server but we have to store the data to our database. So that we need to connect our database to our server.


---

####Connecting Database

1. At first we have to go to our server.js file. And add these lines,


    - `const mongoose = require('mongoose');`
    - `mongoose.connect('mongodb://localhost/blog');`

that's it.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qz4eonqen0kergwqws24.png)

You may face different **deprecations** depending your mongodb version,  like i don't face any depreciations, but if you face deprecations then you have to add it to ,

`mongoose.connect('mongodb://localhost/blog', { useNewUrlPerser: true});` .


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r7qv92l6oxdbaov5nob9.png)



Now we are going to create **mongoose model** that will store the articles.


---


####Mongoose Model



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k77jrirshksgnjulig3z.png)


in article.js we are going to add these,


```
const mongoose = require('mongoose');

const articleSchema = new mongoose.Schema({
    title: {
        type: String,
        required: true
    },
    description: {
        type: String
    },
    markdown:{
        type: String,
        required: true
    },
    craetedAt: {
        type: Date,
        default: Date.now
    }
})

//to export the schema
module.exports = mongoose.model('Article', articleSchema)
```


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9irw7fujqqn6ck59h8yz.png)

okey now we have to access it from 
routes->articles.js,

1.  `const Article = require('./../models/article')`
, This will have the path to models article.js

2. Now we are going to create an object which will receive post data from the user,

```
const article = new Article({

    })
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r9zay1grm3howa9xktgz.png)

but we have to tell express how to access this object. So that we have to go to server.js and add,


`app.use(express.urlencoded({extended: false}))`


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uhs3r4ybxnf9gh47i9fa.png)

after adding this to server.js , we can easily access title, description and markdown of **new article** from routes->articles.js by, req.body.title, req.body.description, req.body.markdown.

```
const express = require('express');

//access model article
const Article = require('./../models/article')
const router = express.Router();

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

router.get('/:id', (req, res) => {

})

router.post('/', async(req, res) =>{
    //to access the form of title, description and markdown we need to tell express how to access them
    const article = new Article({
        title: req.body.title,
        description: req.body.description,
        markdown: req.body.markdown
    })
    try{
        article = await article.save()
        res.redirect(`/articles/${article.id}`)
    }catch(e){
        res.render('articles/new', {article: article })
    }
})

module.exports = router ;
```

after adding all these if we keep the markdown box empty then we click on save, it will show error on terminal.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wq6bfihjzvxfp9igw74d.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c9om9nz6w50lcwu1uhpg.png)

Here the problem is in **server.js** file. we put the article router before the article object.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y34pe7x5hc4dfhfp3dcg.png)

we have to put the article router after the urlencoded. So the updated on is,


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pxmxscbih2e3n8xbac99.png)

so we put , `app.use(express.urlencoded({extended: false}))` this line top and move,  `app.use('/articles', articleRouter);` this line to bottom.


---

###Markdown

1. Because we pass the articles data using ,`res.render('articles/new', {article: article })` this.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gwqbb0iv06if3lhasvf8.png)

we can easily grab those title, description and markdown data and use to our **_form_fields.ejs** file . 

- At first in title we updated the input portion, `<input required value = "<%= article.title %>" type="text" name="title" id="title" class="form-control">`

- Then in description, we add in textarea, `<textarea name="description" id="description" class="form-control"><% article.description %></textarea>`

- And the last in Markdown, we add same as description, `<textarea name="markdown" id="markdown" class="form-control"><% article.markdown %></textarea>`



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dd6vh8xio63nf9dos3fv.png)

 2 . But after adding all these there is some error,

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e2nvo0vf8e08v2p4vv99.png)


 3 .  To solve this we have to add `{article: new Article()}` this to articles.js.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q6v3yo1ws0b5f1yni476.png)


in _form_fields.ejs we made the markdown as required. That means user have to fill this up.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7nzmqnxq81pk7yzidwp7.png)


 4 . But these is some error available , if we click on save btn it will not save the data properly. So the solution is, in article.js we made the article variable constant tried to change its value later which is not possible. So  put let instead of const.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a6qv9adom410qk7fau42.png)


 5 . We can see some error while giving the input, 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kl6sq0q8yw7aa6xcj7cm.png)

That's because we miss the `=` sign in `<%= article.markdown %>` and `<%= article.description %>` of **_form_fields.ejs**.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/36uyg8utq2rqbucaqfe5.png)


 ---


###Render Article

1. At first we are going to edit this portion of articles.js,

```
router.get('/:id', async (req, res) => {
    const article = await Article.findById(req.params.id)
    if(article == null) res.redirect('/')
    res.render('articles/show', {article: article })
})
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5gafd88mm5srqlyovbzs.png)


 2 . we are going to create a new file name **show.ejs** in vies->articles-show.ejs


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l02ksgmghwmc256cwrb1.png)


still i was facing some problem of typeerror of createdAT, i misspelled it on models->artile.js. Previously i typed craetedAt,


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r35ip7tu0r07zn98ahwq.png)


after fixing that,

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yaxja8tw69v0mun0sfw5.png)


---


###Access All the Articles



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ddnyipaytsgkk5ks36je.png)
So instead of these test data we are going to access the newly created data. 

1. We have to go to **server.js**. and we have to remove these portion,
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tdy9lejzx3iu1r7ge40d.png)

and we need to have the access of article model from server.js. its in models->article.js. 

    - `const Article = require('./models/article')`
   
    - `const articles = await Article.find().sort({
        createdAt: 'desc' })`


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j8zldf4nvnfux1a9qhmr.png)



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z4icnfvu7f3mh342ndon.png)



---


###ADD SHOW BUTTON

we are going to create a show btn for our home page. 

1. At first we have to go to our **index.ejs** file. And add this,


     <a href="articles/<%= article.id %>" class="btn btn-primary">Read More</a>



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yaoic6z9rbqedh4tep4o.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7hc3b58u5wo1bk8p9u0h.png)

now we are going to use slug which is the alternative of aticle_id which is slug.

---


###SLUG


  So we are going to import slug library
       
             npm i marked slugify

**marked:** This is a package that allows us to parse Markdown in Node.js. It converts Markdown syntax into HTML.

**slugify:** This package is used to convert a string into a slug, which is a URL-friendly version of the string. It removes special characters, converts spaces to dashes, and makes the string lowercase.

So, when we run npm i marked slugify, npm will download and install both the marked and slugify packages into our project. We can then use these packages in our Node.js code to parse Markdown and create slugs, respectively. 


1. After that we go to models->article.js . And add,

```
const marked = require('marked')
const slugify = require('slugify') 
```

plus,

```
articleSchema.pre('validate', function(next) {
    if(this.title) {
        this.slug = sluggify(this.title, { lower: true,
        strict: true})
    }

    next()
})
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/473154vg605qetro7vrn.png)


 2 . So that to use the slug, we need to do some changes. at first in routes-articles.js,

- `router.get('/:slug', async (req, res) => ` added slug instead of id.

- `const article = await Article.find( { slug: req.params.id })` change the findById and add the slug portion.

- ` res.redirect(`/articles/${article.slug}`)` removed the id and added slug.

But these is some error if you refresh the site.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f6r6mkq5m2anqelmcay7.png)


 3 . To solve this problem we have to go to views->articles->**index.ejs** and change,
- `<a href="articles/<%= article.slug %>" class="btn btn-primary">Read More</a>` change the article.id to article.slug.

and the problem still not solved. so we have to go to the routes->**articles.js** and change,

- const article = await Article.findOne( { slug: req.params.id }) . we change the find to findOne. 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ct6ly67q6yy3tg9bkmd4.png)

###Some type is fixed,
1. in routes->**articles.js** : `const article = await Article.findOne( { slug: req.params.slug })`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mvfrd80k9r4ub5ju9lse.png)

2. And in models->**article.js**: `this.slug = slugify(this.title, { lower: true,`


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oe1b5ih1p62t3ecmz39a.png)


After fixing all these there might show deprecations as it shows in the beginning . Please add those deprecations as we show before in database connect. Its all because of **mongodb** versions



---

##Create DELETE Route

so we can see, only the news articles have the slugs added and the older ones shows nothing.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vhkavyyetr2fknxw62k7.png)

The old ones, 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ygf00raw6sj5z0fr8sdp.png)

Different ones shows different.

To solve these we are going to delete the older ones. To do that we have to create a DELETE Route.

1. At first we have to go to our routes->**articles.js**  and we need the DELETE method so, we have to import it. So that in terminal we use,
   

       npm i method-override


The method-override package lets us use HTTP verbs such as PUT or DELETE in places where the client doesn't support it. This can be useful when handling form data in Express.js, as HTML forms only support GET and POST requests.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f633amdij1tk05d76dk5.png)


 2 . To use this new method we have to go to server.js first. Then add these 2 lines,

-  `const methodOverride = require('method-override')`

- `app.use(methodOverride('_method'))`


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qhoqivv89wg3pk90gb22.png)



###Create DELETE Form

At first we have to go to our **index.ejs** file then,

1.  

```
<form action="/articles/<%= article.id %>?_method=DELETE" method="POST" class="d-inline"><button type="submit" class="btn btn-danger">Delete</button></form>
```


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/52az4w0nm2y6fbdc5v0t.png)


and delete portion is done but there is some typo in routes->articles.js. please correct the spelling of **redirect**.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dp5qxjj1d6jftpx3pwtf.png)


---


###DOM Purify

1. We need to import some packages, 
- `npm i dompurify jsdom`

2. we go to models->**article.js** , and add these on top,

```
const createDomPurify = require('dompurify')
const { JSDOM } = require('jsdom')
const dompurify = createDomPurify(new JSDOM().window)
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kgjzns0282ioqgpphgpv.png)

In image last we wrote createdomPurify which is misspelled. It should be createDomPurify. 


3 . Then we also add these,

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pj5ob6c724k74jof3ugg.png)

```
 sanitizedHtml: {
        type: String,
        required: true
    }
```

and then add these,
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i9pyp38lvxlvtvspao75.png)

```
 if(this.markdown) {
        this.sanitizedHtml = dompurify.sanitized(marked(this.markdwon))
    }
```

next we have to go to **show.ejs** and update,

` <%- article.sanitizedHtml %> `


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pdy4pmlmwh5z1urq2ayk.png)


---

###Edit Blog

so we are in routes->**articles.js** .
1. We add the route,

```
router.get('/edit/:id', async (req, res) => {
    const article = await Article.findById(req.params.id)
    res.render('articles/edit', {article: article})
})
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wjyvxheezr5yirppio1k.png)

and we add a new file to views->articles which is **edit.ejs** . And add,

```
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- bootstrap link -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
    
    <title>Blog</title>
</head>
<body>
    <div class="container">
        <h1 class="mb-4"> Edit Article</h1>

        <form action="/articles/<%= article.id %>?_method=PUT" method="POST">
            <%- include('_form_fields') %>
        </form>
    </div>
</body>
</html>
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/my0owjvri23e002jdd4n.png)




then we add the put method, because put and post methods are same so we are going to use a middleware.


```
function saveArticleAndRedirect(path) {
    return async (req, res) => {
        let article = req.article
            article.title = req.body.title
            article.description = req.body.description
            article.markdown = req.body.markdown
        try{
            article = await article.save()
            res.redirect(`/articles/${article.slug}`)
        }catch(e){
            res.render(`articles/${path}`, {article: article })
        }
    }
}
```


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kergohqcr0umw8chahxx.png)




2. And we also update our **POST** method here,

```
router.post('/', async(req, res, next) =>{
    req.article = new Article()
    next()    
}, saveArticleAndRedirect('new'))
```


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kkmq5o245bhxosrtr4l0.png)


3 . So our post is done now , **PUT** .



but after adding the method it stops working



we will work on it later