problem at rendering views using express.js - node.js

Though my rendering path is correct when I hit http://localhost:4444/admin/posts/create it shows some error like
Error: Failed to lookup view "/admin/posts/create" in views directory "D:\node practise\CMS\views"
app.js file is like
const express = require('express');
const app = express();
const path = require('path');
const exphbs = require('express-handlebars');
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/cms', { useNewUrlParser: true })
.then(db => {
console.log('MONGO CONNECTED!');
})
.catch(error => {
console.log('MONGO NOT CONNECTED!');
})
//making app to use static file
app.use(express.static(path.join(__dirname, 'public')));
//define template engine
app.set('view engine', 'handlebars');
//set default engine
app.engine('handlebars', exphbs({defaultLayout: 'home'}));
//load routes
const home = require("./routes/home/index");
const admin = require("./routes/admin/index");
const posts = require("./routes/admin/posts");
//use routes
app.use(home);
app.use("/admin", admin);
app.use("/admin/posts", posts);
//setting up server
app.listen(4444, () => {
console.log('Listening....');
});
I have posts.js that handles this route like
const express = require("express");
const router = express.Router();
router.all('/*', (req, res, next) => {
req.app.locals.layout = 'admin';
next();
})
router.get('/', (req, res) => {
res.send('It works!');
})
router.get('/create', (req, res) => {
res.render('/admin/posts/create');
})
module.exports = router;
And I have my views folder structure as
What may be the cause of error? When I try to send response it works but when I try to render the view it shows error.

Can you try res.render('admin/posts/create');?
If the view folders is set properly like this: app.set('views', './views'), you should be able to resolve simple view name like res.render('myview') under ./views folder

Related

routing in nodeJs - What could be the reason my routing is not working?

I managed my routing via a few routers, but something went wrong,
when i try to call a functton i get the error:
Error: No default engine was specified and no extension was provided.
I can't understand what could be my problem..
I would be greatfull if soembody can help
my code:
// index.js
const express = require("express");
const router = express.Router();
const userRouter = require("./userRouter");
const qeustionRouter = require("./questionRouter");
const questionToTestRouter = require("./questionToTestRouter");
const testRouter = require("./testRouter");
const subjectRouter = require("./subjectRouter");
/* GET home page. */
router.get("/", function (req, res, next) {
res.render("index", { title: "Express is run" });
});
router.get("/user",userRouter);
router.get("/qeustion",qeustionRouter);
router.get("/questionToTest",questionToTestRouter);
router.get("/test",testRouter);
router.get("/subject",subjectRouter);
module.exports = router;
another router for example:
// userRouter.js
const express = require('express');
const router = express.Router();
const userController = require('../controllers/userController');
router.post('/signUp', userController.signUp)
router.get('/login', userController.login)
router.delete('/deleteStudent', userController.deleteStudent)
router.delete('/deleteTeacher', userController.deleteTeacher)
router.get('/getAllUsers', userController.getAllUsers)
router.get('/getStudentsByTeacherId/:teacherId', userController.getStudentsByTeacherId)
router.get('/getTeachersByStudentId/:userId', userController.getTeachersByStudentId)
router.post('/updateUser', userController.updateUser)
module.exports = router
// app.js
var express = require("express");
var cors = require("cors")
const mongoose = require('mongoose');
//var path = require("path");
// var favicon = require("serve-favicon");
// var logger = require("morgan");
// var cookieParser = require("cookie-parser");
var bodyParser = require("body-parser");
var routes = require("./routes/index");
var app = express();
// view engine setup
// app.set("views", path.join(__dirname, "views"));
// app.set("view engine", "jade");
// // uncomment after placing your favicon in /public
// // app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
// app.use(logger("dev"));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
// app.use(cookieParser());
// app.use(express.static(path.join(__dirname, "public")));
app.use(cors());
app.use("/", routes);
//--------------------------------------
//listen to localhost
app.listen(4000, (req, res) => {
console.log("listening on port 4000");
})
//--------------------------------------
//connect to mongo//
const connectionParams = {
useNewUrlParser: true,
// useCreateIndex: true,
useUnifiedTopology: true
}
mongoose.connect(process.env.DB_CONNECT, connectionParams)
.then(() =>
console.log("connected to mongo"))
.catch((error) =>
console.log("error: " + error))
// catch 404 and forward to error handler
app.use(function (req, res, next) {
var err = new Error("Not Found");
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get("env") === "development") {
app.use(function (err, req, res, next) {
res.status(err.status || 500);
res.render("error", {
message: err.message,
error: err,
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function (err, req, res, next) {
res.status(err.status || 500);
res.render("error", {
message: err.message,
error: {},
});
});
module.exports = app;
I think you need a view engine. I see you are defining "jade" as your view engine but it is commented out and it is not in the index.js
please make sure you installed jade package. You can check this by looking at your package.json file.
npm install jade --save
You need to define jade as your view engine (in the index.js) and your jade files must be stored inside the views folder. Inside index.js file, you can change all router keywords to app
const express = require ("express");
const app = express ();
app.set("view engine","jade")
And delete this: const router = express.Router();
And this folder must be placed at the root of your project (in other words, your index.js file and "views" folder should be at the same level). If you do it in this way, you wont need to define a path route.
I kindly advise you to use "ejs" as your view engine. It is more common than "jade". You can create ejs files easily, just like an html page.
And first start with a single route to test if your express framework is working. You can then gradually add up other routes. And please let me know if this answer helps, otherwise I will delete.

My Nodemon app is crashed when I try to run it

I am trying to run my webapp using mongodb but I am constantly getting error of app crashed. I have rechecked everything but it is still causing error. Can anyone help me with it?
server.js:
if (process.env.NODE_ENV !== 'production') {
require('dotenv').config()
}
const express = require('express')
const app = express()
const expressLayouts = require('express-ejs-layouts')
const indexRouter = require('./routes/index')
const authorRouter = require('./routes/authors')
app.set('view engine', 'ejs')
app.set('views', __dirname + '/views')
app.set('layout', 'layouts/layout')
app.use(expressLayouts)
app.use(express.static('public'))
const mongoose = require('mongoose')
mongoose.connect(process.env.DATABASE_URL, { useNewUrlParser: true })
const db = mongoose.connection
db.on('error', error => console.error(error))
db.once('open', () => console.log('Connected to Mongoose'))
app.use('/', indexRouter)
app.use('/authors', authorRouter)
app.listen(process.env.PORT || 3000)
author.js
const mongoose = require('mongoose')
const authorSchema = new mongoose.Schema({
name: {
type: String,
required: true
}
})
module.exports = mongoose.model('Author', authorSchema)
I have separate folder for routes for authors. The above author is author model and this one file is for /authors route.
authors.js:
const express = require('express')
const router = express.Router()
const Author = require('../models/author')
// All Authors Route
router.get('/', (req, res) => {
res.render('authors/index')
})
// New Author Route
router.get('/new', (req, res) => {
res.render('authors/new', { author: new Author() })
})
// Create Author Route
router.post('/', (req, res) => {
res.send('Create')
})
module.exports = router
I get this error
[nodemon] app crashed - waiting for file changes before starting...

How can I prevent express-ejs-layouts for wrapping my other page?

I'm finding a page layout for node.js like laravel php have their Template for layout and it is perfect. I want to achieve it here in node.js and finally found this express-ejs-layouts but there is a problem in it that I cant see in their documentation the layout will wrap all of my pages specially my signin and signup page which have a different header and footer. How can we prevent express-ejs-layouts from wrapping my other page?
const express = require('express');
const router = express.Router();
const path = require('path');
const multer = require('multer');
const bodyParser = require('body-parser');
const mysql = require('mysql');
const app = express();
const server = require('http').createServer(app);
const expressLayouts = require('express-ejs-layouts');
// Set Database Connection
const connection=mysql.createConnection({
host:'localhost',
user:'root',
password:'',
database:'project_101'
});
connection.connect(function(error){
if(!!error) console.log(error);
else console.log('Database Connected!');
});
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.static('assets'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(bodyParser.urlencoded({extended: true}));
app.use(expressLayouts);
app.get('/',(req, res) => {
let sql = "SELECT * FROM uploads";
let query = connection.query(sql, (err, rows) => {
if(err) throw err;
res.render('index');
});
});
app.get('/signup', (req, res) => {
res.render('signup');
});
app.get('/signin', (req, res) => {
res.render('signin');
});
app.get('/unknown-user', (req, res) => {
res.render('unknown-user');
});
app.get('/profile', (req, res) => {
res.render('profile');
});
const port = process.env.PORT || 3000;
// Server Listening
server.listen(port, function () {
console.log('Server successfully running at: -',port);
});
Finally got the solution for the problem express-ejs-layouts
const express = require('express');
const expressLayouts = require('express-ejs-layouts');
app.use(expressLayouts);
You just need to declare your page as a layout and set it to false.
app.set("layout signin", false);
and render the page together with the layout.
app.get('/signin', (req, res) => {
res.render('signin', { layout: 'signin' });
});
ez fix ⚡️
You can bypass the template by sending the file back.
res.sendFile(path, options, fn);
options and fn are optional.

I cannot get /users json

I'm new to express and node js, I recently learned how to write API for express but at the end, I get some sort of problem which not resolved by me after several tries. I could not get a response on localhost:8080/users
src/routes/users.js
const { Router } = require("express");
const router = Router();
const getUsers = (req, res) =>
res.send(Object.values(req.context.models.users));
const getUser = (req, res) =>
res.send(req.context.models.users[req.params.userId]);
router.get("/users/", getUsers);
router.get("/users/:userId", getUser);
module.exports = router;
src/routes/index.js
const user = require("./user");
const message = require("./message");
module.exports = {
user,
message
};
src/index.js
const express = require("express");
const app = express();
// Custom Modules
const routes = require("./routes");
const models = require("./models");
// Application-Level Middleware Starts
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use((req, res, next) => {
req.context = {
models,
me: models.users[1]
};
console.log(req.context.models.users);
next();
});
// Used Routes
app.use("/users", routes.user);
app.use("/messages", routes.message);
// App Listning to HTTPS Module
app.listen(process.env.PORT);
You need to fix your endpoints in users.js:
router.get("/", getUsers);
router.get("/:userId", getUser);
The reason is because of app.use("/users", routes.user); in your index.js, where the endpoint for users is set. If you leave /users/ in users.js it would be localhost:8080/users/users/. Same problem might be with /messages.

express route unable to get

I have a route file for the admin and home pages separately. I also have difference layout files for home and admin. When I access the home and admin routes on my local dev everything is ok, but when I try to access the admin route useing site.com/admin I get Cannot GET /admin/ response. following is my server.js:
const express = require('express');
const exphbs = require('express-handlebars');
const methodOverride = require('method-override');
const flash = require('connect-flash');
const session = require('express-session');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const path = require('path');
const app = express();
// Use path
app.use(express.static(path.join(__dirname, 'public')));
// Map Global Promise
mongoose.Promise = global.Promise;
// Connect to mongoose
mongoose.connect('mongodb://localhost/skillbuild')
.then(() => console.log('MongoDB Connected...'))
.catch(err => console.log(err));
// Load Idea model
// require('./models/Idea');
// const Idea = mongoose.model('ideas');
// Express Handlebars middleware
app.engine('handlebars', exphbs({
defaultLayout: 'main'
}));
app.set('view engine', 'handlebars');
// BodyParser middleware
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// Method Override middleware
app.use(methodOverride('_method'));
// Load routes
const home = require('./routes/home');
const admin = require('./routes/admin');
// Use routes
app.use('/', home);
app.use('/admin', admin);
// Express session middleware
app.use(session({
secret: 'keyboard cat',
resave: true,
saveUninitialized: true
}));
app.use(flash());
// Global variables
app.use(function (req, res, next) {
res.locals.success_msg = req.flash('success_msg');
res.locals.error_msg = req.flash('error_msg');
res.locals.error = req.flash('error');
next();
});
const port = 80;
app.listen(port, () => {
console.log(`Server started on port ${port}`);
});
my home routes which are in home.js routes file:
const express = require('express');
const router = express.Router();
router.all('/*', (req, res, next) => {
req.app.locals.layout = 'main';
next();
});
// index route
router.get('/', (req, res) => {
res.render('index');
});
// About route
router.get('/about', (req, res) => {
res.render('about');
});
//login route temp
router.get('/login', (req, res) => {
res.render('users/login');
});
module.exports = router;
my admin.js routes file:
const express = require('express');
const router = express.Router();
router.all('/*', (req, res, next) => {
req.app.locals.layout = 'admin';
next();
});
// admin index route
router.get('/', (req, res) => {
res.render('admin/index');
});
module.exports = router;
OK...so the problem simply was that I needed to restart the server with pm2 restart id of the node app in order to load the updated code. Problem solved.

Resources