I am new in nodejs and I faced a problem I can't solve, I searched on google but I don't find any solutions, I have used pagination on my website it's working fine but after I added the layout is not working and give me error !!!
Error: Missing helper: "paginate"
this is my code where is wrong ?? I am using handlebars and MySQL DB
server.js
const path = require('path')
const exphbs = require('express-handlebars');
const helpers = require('handlebars-helpers')
const Handlebars = require('hbs');
var paginateHelper = require('express-handlebars-paginate');
//Register Helper
Handlebars.registerHelper('paginate', require('handlebars-
paginate'));
app.set('view engine', '.hbs');
app.engine('hbs', exphbs.engine({
extname: 'hbs', runtimeOptions: {
allowProtoPropertiesByDefault: true,
allowProtoMethodsByDefault: true,
// allowCallsToHelperMissing: true,
},
defaultLayout: 'main',
layoutsDir: path.join(__dirname + '/views/layouts/'),
partialsDir: path.join( __dirname + '/views/partials/'),
helpers:{
paginateHelper: require('express-handlebars-
paginate').createPagination
}
}))
app.use(express.static('public'));
app.use(express.json());
app.use(express.urlencoded({extended : true}));
app.use(cors())
app.use(bodyParser.json())
app.use(session({
secret:"secret",
resave:true,
saveUninitialized:true
}))
question.js
const db = require('../models')
const Handlebars = require('hbs');
Handlebars.registerHelper('paginate', require('handlebars-
paginate'));
const Users = db.users
const Question = db.questions
const UserAnswer = db.user_answer
const category = db.category
const reviewQuestion = async (req, res) =>{
console.log(req.params.num)
const Q_A = [];
const questions = await Question.findAll({
raw:true,
include: [{
model: category,
attributes : ['category_name'],
where: {id: req.params.num},
}]
}).then( async (dbQuestions)=>{
for ( let question of dbQuestions){
// console.log(question)
const answer = await UserAnswer.findOne({ where: {
questionId : question.id, userId:req.params.id },
raw:true,
required: false
}).then((answer)=>{
const qA = Object.assign({}, question, answer)
Q_A.push(qA);
});
}
});
console.log(Q_A)
res.render('./user/Question-Answer/questions', { layouy:false,
questions: Q_A,
pagination: {
page: req.params.num || 1,
pageCount: 7
},
})
}
questions.hbs (pagination part)
<div class="pagination pagination-centered, center" >
<ul class="paginate">
{{#paginate pagination type="previous"}}
<li {{#if disabled}} class="pageNumber disabled"
{{/if}}>السابق</li>
{{/paginate}}
{{#paginate pagination type="middle"
limit=pagination.pageCount}}
<li {{#if active}} class="pageNumber active"
{{/if}}>{{n}}</li>
{{/paginate}}
{{#paginate pagination type="next"}}
<li {{#if disabled}} class="pageNumber disabled"
{{/if}}>التالي</li>
{{/paginate}}
</ul>
</div>
<div class="container">
<div class="register">
<button type="submit" id="register-link">حفظ لاحقًا</button>
<a href="./questionsdone"><button type="submit"
formaction="./questionsdone" id="register-link">إرسال </button>
</a>
</div>
</div>
</div>
error
Error: Missing helper: "paginate"
help me please, thank you
I added helper in server but not working
`app.set('view engine', '.hbs');
app.engine('hbs', exphbs.engine({
extname: 'hbs', runtimeOptions: {
allowProtoPropertiesByDefault: true,
allowProtoMethodsByDefault: true,
// allowCallsToHelperMissing: true,
},
defaultLayout: 'main',
layoutsDir: path.join(__dirname + '/views/layouts/'),
partialsDir: path.join( __dirname + '/views/partials/'),
helpers:{
paginateHelper: require('express-handlebars-paginate').createPagination
}
}))`
Related
I have done the first part correctly (upload the images to their folders), but I can't
upload the images to the DB
form.html
the form to upload the images while the user sign up for a new account
<div>
<label for="image">Upload Image</label>
<input type="file" id="image1" name="image1" value="" >
</div><div>
<label for="image">Upload Image</label>
<input type="file" id="image2" name="image2" value="" >
</div>
multer.js
to save the images in the folders
const path = require('path');
const multer = require('multer');
const storage = multer.diskStorage({
destination: (req, file, cb) => {
if (file.fieldname === 'image1') {
cb(null, './logic/uploads');
}
else if (file.fieldname === 'image2') {
cb(null, './logic/uploadp');
}
},
filename: (req, file, cb) => {
cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname));
console.log('New image saved!')
}
});
module.exports = multer({ storage: storage });
route
const express = require('express');
const router = express.Router();
const multer = require('../logic/multer')
const { userSignup, userLogin } = require('../logic/Membership_Application');
router.post('/Register',
multer.fields([
{ name: 'image1', maxCount: 1 },
{ name: 'image2', maxCount: 1 },
]),
userSignup
);
router.post('/login', userLogin);
module.exports = router;
logic (data insertion)
const UsersSchema = await new jcs({
name: req.body.name,
email: req.body.email,
phone: req.body.phone,
password: hashedPassword,
nationality: req.body.nationality,
//here is the error(it was working with multer.singel but not with multer,fields)
img: {
data: fs.readFileSync(path.join(__dirname + '/uploads/' + req.file.filename)),
contentType: 'image/png'
},
img2: {
data: fs.readFileSync(path.join(__dirname + '/uploadp/' + req.file.filename)),
contentType: 'image/png'
}
}).save();
model(Database schema)
const db = require('mongoose');
//Database Creation
const UsersSchema = new db.Schema
({
name: { type: String },
email: { type: String },
phone: { type: String },
password: { type: String },
nationality: { type: String },
img:
{
data: Buffer,
contentType: String,
},
img2:
{
data: Buffer,
contentType: String,
},
})
var Users = db.model("Users", UsersSchema);
module.exports = Users;
app.js
const express = require('express');
const app = express();
require('dotenv/config');
const MembershipApplicationRouter = require('./route/Membership_Application');
const AdminRouter = require('./route/admin')
var bodyParser = require('body-parser');
const cors = require('cors');
const db = require('mongoose');
db.connect('mongodb-link',
{
useNewUrlParser: true,
useUnifiedTopology: true
});
const connection = db.connection;
connection.on('connected', () => { console.log("conected with cloud") });
connection.on('error', () => { console.log("error with database") });
app.use('/admin', AdminRouter);
app.use([
bodyParser.urlencoded({ extended: true }),
express.json(),
express.urlencoded({ extended: true })]);
app.use(cors());
app.use('/membershipApplication', MembershipApplicationRouter);
var port = process.env.PORT || 8080;
app.listen(port, () => {
console.log("Server Up and running");
})
module.exports = app;
I have this error msg
New image saved!
New image saved!
C:\Users\abs2\Desktop\m_a_test\logic\Membership_Application.js:79
data: fs.readFileSync(path.join(__dirname + '/uploads/' + req.file.filename)),
^
TypeError: Cannot read properties of undefined (reading 'filename')
at userSignup (C:\Users\abs2\Desktop\m_a_test\logic\Membership_Application.js:79:84)
[nodemon] app crashed - waiting for file changes before starting...
The best practice is to store the file’s location in your server to mongoDB.
So that whenever you to access the file you fetch it’s location then return it back!!
I am trying to send a template form node js using nodemailer and express-handlebars but I'm getting the error no such file I have no idea what I'm missing
I'm attaching my index.js down
const express = require('express')
const app = express()
const bodyParser = require('body-parser')
const hb = require('nodemailer-express-handlebars')
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json())
const nodemailer = require('nodemailer');
const { google } = require('googleapis');
const path = require('path');
// These id's and secrets should come from .env file.
const CLIENT_ID = 'the id';
const CLEINT_SECRET = 'the secret';
const REDIRECT_URI = 'uri';
const REFRESH_TOKEN = 'the token';
const oAuth2Client = new google.auth.OAuth2(
CLIENT_ID,
CLEINT_SECRET,
REDIRECT_URI
);
oAuth2Client.setCredentials({ refresh_token: REFRESH_TOKEN });
app.post("/api", async (req,res) => {
try{
const accessToken = await oAuth2Client.getAccessToken();
const transport = nodemailer.createTransport({
service: 'gmail',
auth: {
type: 'OAuth2',
user: 'your [enter image description here][1]emial',
clientId: CLIENT_ID,
clientSecret: CLEINT_SECRET,
refreshToken: REFRESH_TOKEN,
accessToken: accessToken,
},
})
const handlebarOptions = {
viewEngine: {
extName: ".handlebars",
partialsDir: path.resolve(__dirname, "emialTemplate"),
defaultLayout: false,
},
viewPath: path.resolve(__dirname, "emialTemplate"),
extName: ".handlebars",
};
transport.use(
"compile",
hb(handlebarOptions)
);
// the data which we going to send
const mailOptions = {
from: req.body.name + '<ummed.gagrana#gmail.com>',
to: 'ummed.gagrana#gmail.com',
subject: req.body.subject,
text: "From:" + req.body.email + "\n Message:" + req.body.message,
// html: '<h2>From:</h2>'+'<h4>'+req.body.email+"</h4> <br>"+"<h2>Message:</h2>"+'<h4>'+req.body.message+"</h4>",
template: 'comeBack'
};
//sending mail
const result = await transport.sendMail(mailOptions);
// checking the result after sending mail
console.log(result)
res.send({hey:"well done you just paased some data"})
} catch (error) {
console.log(error)
}
})
app.listen(3000, () => {
console.log("server up and running on port 3000")
})
This the code I am not sure what I'm missing I'm a beginner in nodejs so please help
I am attaching my work directory path for help
[]
You got a typo. emialTemplate --> emailTemplate
const handlebarOptions = {
viewEngine: {
extName: ".handlebars",
partialsDir: path.resolve(__dirname, "emailTemplate"),
defaultLayout: false,
},
viewPath: path.resolve(__dirname, "emailTemplate"),
extName: ".handlebars",
};
After that, I would return the following code line to tell the server that the code has been processed as it should have.
return res.send({hey:"well done you just paased some data"})
I just studying mongodb and node.js, and i met a problem. I need to write a request so that when I click on the "Rent" button the document moves to rent and disappears from the available ones. How do I implement this?
Sorry if it stupid question.
app
Schema:
const { Schema, model } = require('mongoose')
const schema = new Schema({
title: {
type: String,
required: true
},
type: {
type: String,
default: false
},
price: {
type: Number,
default: false
}
})
module.exports = model('Rent', schema)
html of available :
<div class="rent__title">
<img src="https://emojio.ru/images/apple-b/1f6b2.png" alt="">
<h2 id="rh">Available bicycles </h2>
</div>
<div class="rent__list">
{{#if rents.length}}
<ul class="ul">
{{#each rents}}
<li class="rent">
<form action="/rented" method="POST">
<label>
{{#if completed}}
<span class="aval">{{title}}   /   {{type}}  /   {{price}}</span>
{{/if}}
<input type="hidden" value="{{_id}}" name="id">
<span class="rent__buttons">
<button formaction="/rented" class="btn b1" >Rent</button>
<button formaction="/delete" class="btn b2" >Delete</button>
</span>
</label>
</form>
</li>
{{/each}}
</ul>
{{else}}
<p>No rent!</p>
{{/if}}
</div>
routes:
const { Router } = require('express')
const Todo = require('../models/Todo')
const Rented = require('../models/Todo')
const router = Router()
router.get('/', async (req, res) => {
const todos = await Todo.find({})
res.render('index', {
title: 'Todos list',
isIndex: true,
todos
})
})
router.get('/create', (req, res) => {
res.render('create', {
title: 'Create new rent',
type: 'Choose type',
price: '$',
status: 'false',
isCreate: true
})
})
router.post('/create', async (req, res) => {
const todo = new Todo({
title: req.body.title,
type: req.body.type,
price: req.body.price
})
await todo.save()
res.redirect('/')
})
router.post('/rented', async (req, res) => {
const rent = await Todo.findById(req.body.id)
rent.rented = !!req.body.rented
await rent.save()
res.redirect('/')
})
router.post('/delete', async (req, res) => {
const todo = await Todo.findByIdAndRemove(req.body.id)
await todo.save()
res.redirect('/')
});
module.exports = router
Add a new route as
router.get('/getRented', async (req, res) => {
const todos = await Todo.find({rented:true})
res.render('rented', {
title: 'Rented Todos list',
isIndex: true,
todos
})
})
router.post('/rented', async (req, res) => {
//req.body.id
//update this code by rented:true
})
I am trying to upload a file from my page to node server.
I can see form data are arriving in the router on server.
But no file is saved in upload folder.
What am I doing wrong?
//router unit
const express = require('express');
const router = express.Router();
const multer = require('multer');
const storage = multer.diskStorage({
destination: (req, file, cb) => {
console.log('chegei')
cb(null, "uploads/")
},
filename: (req, file, cb) => {
console.log('chegei2')
cb(null, Date.now() + "-" + file.ogirinalname)
},
});
module.exports = function (page) {
router.post('/SendMsgBase64', async (req, res) => {
var upload = multer({ storage: storage }).single('userFile');
upload(req, res, function (err) {
if (err) {
console.log(err);
return res.send({ "data": "Error uploading file." });
}
return res.send({ "data": "File is uploaded" });
});
return router
}
//app.js unit
const express = require('express')
const app = express()
const server = require('http').Server(app)
const io = require('socket.io')(server)
const WARoutes = require('../routes/WARoutes');
const path = require('path');
const bodyParser = require('body-parser');
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
app.use(express.urlencoded({ extended: true }))
app.get('/', (req, res) => {
res.sendFile('/index.html');
})
app.use('/whats', WARoutes(this.page));
//html
<form id="uploadForm">
<input type="file" name="userFile" />
<input type="button" value="Upload Image" onclick="uploadFile();">
<span id="status"></span>
</form>
<script>
uploadFile = () => {
var formData = new FormData();
debugger
var logoImg = $('input[name="userFile"]').get(0).files[0];
formData.append('logo', logoImg);
var objArr = [];
objArr.push({ "id": "123", "name": "luiz" });
//JSON obj
formData.append('objArr', JSON.stringify(objArr));
$.ajax({
url: "/whats/SendMsgBase64",
type: "POST",
processData: false,
contentType: "application/x-www-form-urlencoded",
data: formData,
complete: function (data) {
alert("success");
}
})
};
</script>
According to multer's github page, if you have not created the uploads directory, it may go something wrong.
If this is the case, creating the directory on your own or passing a string value to destination property is the solution for you.
https://github.com/expressjs/multer
Note: You are responsible for creating the directory when providing destination as a function. When passing a string, multer will make sure that the directory is created for you.
i have created a template using handlebars.i need to change certain variables after of if user is logged in.
that could be done by passing the value to variable when rendering the page.
but i need to change the value of my main template that is the default layout.
here is the part of the code
<a class="nav-link nav-link-white dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{account or user name here}}
<i class="fas fa-chevron-down ml-2"></i>
</a>
here is my app file
var express = require('express')
var app = express()
var passport = require('passport')
var session = require('express-session')
var bodyParser = require('body-parser')
var env = require('dotenv').config()
var exphbs = require('express-handlebars')
var path = require("path") //added
app.use(express.static('public'));
//For BodyParser
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// For Passport
app.use(session({ secret: 'key', resave: true, saveUninitialized: true })); // session secret
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
//For Handlebars
app.set('views', './app/views')
app.engine('hbs', exphbs({ extname: '.hbs', defaultLayout: "main", layoutsDir: path.join(__dirname,"app/views") }));
app.set('view engine', '.hbs');
app.get('/', function (req, res) {
//res.send('Welcome to Passport with Sequelize');
//res.sendFile(path.join(__dirname + '/index.html')); //added
res.render('home');
});
app.get('/dashboard', function (req, res) {
res.render('dashboard');
});
//app.get('/bags', function (req, res) {
// res.render('bags');
//});
//Models
var models = require("./app/models");
//Routes
var authRoute = require('./app/routes/auth.js')(app, passport);
//load passport strategies
require('./app/config/passport/passport.js')(passport, models.user);
//Sync Database
models.sequelize.sync().then(function () {
console.log('Nice! Database looks fine')
}).catch(function (err) {
console.log(err, "Something went wrong with the Database Update!")
});
app.listen(5000, function (err) {
if (!err)
console.log("Site is live"); else console.log(err)
});
this is my route
var authController = require('../controllers/authcontroller.js');
module.exports = function (app, passport) {
app.get('/signup', authController.signup);
app.get('/signin', authController.signin);
app.post('/signup', passport.authenticate('local-signup', {
successRedirect: '/dashboard',
failureRedirect: '/signup'
}
));
app.get('/bags', authController.bags)
app.get('/productpage', authController.productpage)
app.get('/dashboard', isLoggedIn, authController.dashboard);
app.get('/logout', authController.logout);
app.post('/signin', passport.authenticate('local-signin', {
successRedirect: '/dashboard',
failureRedirect: '/signin'
}
));
function isLoggedIn(req, res, next) {
if (req.isAuthenticated())
return next();
res.redirect('/signin');
}
}