title: Expressjs Turning Dynamic Uppercase and Spaced Route paths into Hyphenated and lowercase Routes
body: <p>I am running into an issue where I am trying to use the "title" property from my mongoosedb documents as a document path, but with all of the characters lowercase and the spaces replaced with hyphens. I tried to use a solution before, but wasn't able to generate my view and the Url's contained uppercase letters and %20 for the spaces.</p>
  
  <p>Here is my current setup The focus is on the <code>'/blog/:blogpost_title'</code> route:</p>
  
  <p>routes.js:</p>
  
  <pre><code>var express = require('express');
  var router = express.Router();
  var blogDB = require('../config/blogDB.js');
  var Blogpost = require('./models/blogModel.js');
  var paginate = require('express-paginate');
  
  //index 
  router.use(paginate.middleware(10, 50));
  
  
  
  
      router.route('/') 
  
  
          // START GET method
          .get(function(req, res, next) {
  
              Blogpost.paginate({}, req.query.page, req.query.limit, function(err, pageCount, blogpost, itemCount) {
  
  
  
  
                  if (err) return next(err)
  
                          if (err)
                              res.send(err);
  
  
                          blogpost.title = req.body.title; // get the blog title
                          blogpost.author = req.body.author; // get the author name
                          blogpost.tagline = req.body.tagline; // get tagline
                          blogpost.content = req.body.content; // get the blog content
                          blogpost.category = req.body.category; // get the category
                          blogpost.tags = req.body.tags; // get the tags
  
  
                          res.format({
                              html: function() {
                                  res.render('pages/index', {
                                      blogpost: blogpost,
                                      pageCount: pageCount,
                                      itemCount: itemCount
                                  })
                              },
                              json: function() {
  
                                  res.json({
                                      object: 'blogpost',
                                      has_more: paginate.hasNextPages(req)(pageCount),
                                      data: blogpost
                                  })
                              }
                          }); // END res.format(html, json)
              }); // END Blogpost.paginate
          }); // END GET method
  
  router.route('/admin/posts/create')
  
      // START POST method
          .post(function(req, res) {
  
              var blogpost = new Blogpost(); // create a new instance of a Blogpost model
  
              blogpost.title = req.body.title; // set the blog title
              blogpost.author = req.body.author; // set the author name
              blogpost.tagline = req.body.tagline; // set the tagline
              blogpost.content = req.body.content; // set the blog content
              blogpost.category = req.body.category; // set the category
              blogpost.tags = req.body.tags; // set the tags
                  //Save Blog Post
                  blogpost.save(function(err) {
                      if (err)
                          res.send(err);
  
                      res.redirect(303, '/'); //NEEDS TO BE CHANGED
                  });
  
          }) // END POST method
  
  
          .get(function(req, res) {
              res.render('pages/blogpost-create');
          });
  
  function getSearchCriteria(params) {
        return {
            title: params.blogpost_title
        };
  }
  
  function getBlogpostUpdate(body) {
        return {
             title: body.title,
             author: body.author,
             tagline: body.tagline,
             content: body.content,
             category: body.category,
             tags: body.tags
        };
  }
  
  var blogpostsRoute = router.route('/blog/:blogpost_title');
  
  // to manipulate your route params, use router.param
  router.param('blogpost_title', function (req, res, next, blogpost_title) {
      req.params.blogpost_title = blogpost_title.toLowerCase();
      next();
  });
  
  blogpostsRoute 
      .get(function (req, res) {
           var searchCriteria = getSearchCriteria(req.params);
           Blogpost.findOne(searchCriteria, function (err, blogpost) {
               if (err)
                   res.send(err);
               res.render('pages/blogpost', {
                   blogpost: blogpost
               })
           })
       })
       .put(function (req, res) {
           var searchCriteria = getSearchCriteria(req.params);
           var updated = getBlogpostUpdate(req.body)
           Blogpost.findOneAndUpdate(searchCriteria, updated, function (err, updated) {
               if (err)
                   res.send(err);
  
  
               res.json({ message: 'Blog updated.' });
           });
       })
       .delete(function (req, res) {
           var searchCriteria = getSearchCriteria(req.params);
           Blogpost.findOneAndRemove(searchCriteria, function (err, removed) {
               if (err)
                  res.send(err);
  
               res.json({ message: 'Successfully deleted' });
           });
       });
  
  //about
      router.get('/about', function(req, res) {
              res.render('pages/about');
      });
  
  //resume
      router.get('/resume', function(req, res) {
              res.render('pages/resume');
      });
  
  
  
  module.exports = router;
  </code></pre>
  
  <p>index.ejs:</p>
  
  <pre><code>&lt;div class="grid"&gt;
      &lt;div class="col-9-12"&gt;
          &lt;div class="blog-content"&gt;
              &lt;% blogpost.forEach(function(blogpost) { %&gt;
                  &lt;tr&gt;
                      &lt;td&gt;&lt;h2&gt;&lt;a href="#" class="blog-title"&gt;&lt;%= blogpost.title %&gt;&lt;/a&gt;&lt;/h2&gt;&lt;/td&gt;
                      &lt;td&gt;&lt;h3&gt;&lt;%= blogpost.date %&gt;&lt;/h3&gt;&lt;/td&gt;
                      &lt;td&gt;&lt;h3 class="blog-category"&gt;&lt;%= blogpost.category %&gt;&lt;/h3&gt;&lt;/td&gt;
                      &lt;td&gt;&lt;h3 class="blog-tagline"&gt;&lt;i&gt;&lt;%= blogpost.tagline %&gt;&lt;/i&gt;&lt;/h3&gt;&lt;/td&gt;
                      &lt;td&gt;&lt;p&gt;&lt;%=: blogpost.content | truncate:800 | append:'...' %&gt;&lt;/p&gt;&lt;/td&gt;
                      &lt;td&gt;&lt;a href="/blog/&lt;%= blogpost.title %&gt;" class="blog-read-more"&gt;Read More&lt;/a&gt;&lt;/td&gt;
                  &lt;/tr&gt;
                  &lt;% }); %&gt;
          &lt;/div&gt;
      &lt;/div&gt;
  </code></pre>
  
  <p>blogModel.js</p>
  
  <pre><code>var mongoose    = require('mongoose');
  var mongoosePaginate = require('mongoose-paginate');
  var Schema      = mongoose.Schema;
  
  
  
  var BlogPostSchema  = new Schema({
          title: String,
          author: String,
          tagline: String,
          category: String,
          content: String,
          tags: { type: String, lowercase: true },
          date: { type: Date, default: Date.now }
  });
  
  BlogPostSchema.plugin( mongoosePaginate );
  
  var Blogpost = mongoose.model("Blogpost", BlogPostSchema);
  
  
  
  module.exports = mongoose.model('Blogpost', BlogPostSchema);
  </code></pre>