Express and Jade, passing in variables - node.js

I'm trying to install this captcha plugin and this is what I have so far (straight from their code, just kind of tweaked up to my style)
Here is captcha and steps I'm following: https://github.com/mirhampt/node-recaptcha
In my router.js file:
app.get('/account/verification/:token/', require('./views/account/verification/index').verifyHuman);
In my /views/account/verification/index.js file:
exports.verifyHuman = function(req, res, next){
var Recaptcha = require('recaptcha').Recaptcha;
var recaptchaKeys = req.app.config.recaptchaKeys;
var recaptcha = new Recaptcha(recaptchaKeys.publicKey, recaptchaKeys.privateKey);
console.log(recaptcha.toHTML()); //this returns a script tag with an iframe and stuff in it
res.render('account/verification/captcha', {
layout: false,
locals: {
recaptcha_form: recaptcha.toHTML()
}
});
};
and then my /views/account/verification/captcha.jade file:
div#captcha
script(type='text/template', id='tmpl-captcha-verification')
form#captcha-verification
#{recaptcha_form}
button.btn.btn-primary.btn-captcha-verification(type='button') Check Captcha
I can't get it do display the captcha script. It comes up as undefined but in a strange way. This is what appears in my console:
<script type="text/template" id="tmpl-captcha-verification"><form id="captcha-verification"><undefined></undefined><button type="button" class="btn btn-primary btn-captcha-verification">Check Captcha</button></form></script>
I can even try and do #{layout}, and I get this in the console:
<script type="text/template" id="tmpl-captcha-verification"><form id="captcha-verification"><false></false><button type="button" class="btn btn-primary btn-captcha-verification">Check Captcha</button></form></script>
It's like jade is trying to format it, but one of the main issues is that it's undefined, when the variable in my /views/account/verification/index.js file that I console.log isn't.
Also, note that if I do != recaptcha_form, it just shows the form in the html as it would if this != recaptcha_form code wasn't even there.
I've searched around other questions for this answer and am still pretty confused. Any help would be greatly appreciated. Thanks

Related

Reset Password Page Not Rendering Correctly When Accessing from Reset Email Link

Ok, so first off, this is my first post. I've searched high and low for a solution, but have found none. I have posted this first on Udemy, for the course I've taken, but no one has answered, so I'm reposting it here.
I have been trying very hard to figure out why the new-password page will not display correctly for me. The reset link works fine, and I can even reset the password on my new password page when I am sent there from the email link.
However, no matter what I do, I can't get it to display any styling. It only gives me basic html. The logic works fine, it's just the page that doesn't display correctly.
I know it isn't a path issue to the css folder either. If I simply render as another basic page without any token logic, such as replacing my index page with the new-password page, then it displays normally. I just don't know what I'm missing, or if there was some updates that I need to take into consideration.
I'm hoping someone sees this and can help me out. It's the only thing that doesn't work right, and it's very frustrating.
Just to be a little more clear, if I do something like below, and just replace or create a route, the page shows up correctly. It's the token logic I believe that is breaking the rendering, I just don't know how, since I don't get any errors.
Please let me know what code you may need to see, as I'm not sure what sections would be helpful, there are a lot of moving parts here. I will be happy to post whatever is needed.
exports.getNewPassword = (req, res, next) => {
res.render("auth/new-password", {
path: "/new-password",
pageTitle: "Update Password",
});
};
With the logic built-in and following the email reset link, the below will not render any styling, only the html.
exports.getNewPassword = (req, res) => {
const token = req.params.token;
User.findOne({
resetToken: token,
resetTokenExpiration: { $gt: Date.now() },
})
.then((user) => {
if (!user) {
req.flash(
"error",
"That reset password link has already been used."
);
return res.redirect("/");
}
let message = req.flash("error");
message.length > 0 ? (message = message[0]) : (message = null);
res.render("auth/new-password", {
path: "/new-password",
pageTitle: "New Password",
errorMessage: message,
userId: user._id.toString(),
passwordToken: token,
});
})
.catch((err) => console.log(err));
};
I am using ejs for templating as well. As I said above, if I remove all token logic and just render the page as a normal view, it works fine.
<main>
<% if (errorMessage) { %>
<div class="user-message user-message--error"><%= errorMessage %></div>
<% } %>
<form class="login-form" action="/new-password" method="POST">
<div class="form-control">
<label for="password">Password</label>
<input type="password" name="password" id="password">
</div>
<input type="hidden" name="userId" value="<%= userId %>">
<input type="hidden" name="passwordToken" value="<%= passwordToken %>">
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
<button class="btn" type="submit">Update Password</button>
</form>
</main>
Well, in case anyone stumbles across this, the answer was pretty simple, though I'm not sure why in this one instance is was a problem. However, the solution was to add a forward slash in front of my path to the css location for the update password page.
Again, not sure why it needed it, seeing as all my other css and view pages were in the same folder structures and worked fine, but it apparently solved the issue. SMDH.
<link rel="stylesheet" href="/css/login.css" />

POST FORM in node and receive data response back to same webpage

I have a webpage that takes form details, POSTS the data and should then show the results. I'm using express for my routing.
This all works fine by resending the data with the HTML template after the POST but I think there must be a better way by hiding the "results" HTML section then just showing it once the data is known from the form. I've shown a cutdown version of my pages below.
On first load, the page says "your result is undefined", which I would expect but is ugly.
I could remove the "result" section and create a 2nd HTML page to resend from the POST route with it in which would work but I think there must be a better way.
I want to hide the result section on 1st page load then make it appear on the button submit with the result data. I can get the section hide/unhide but I can't get the data results back to display them. On button submit the form results just appear in the weburl www.mywebsite.com/?data almost like a GET request
I have tried using FormData and npm 'form-data' in a POST but can't get it working following these examples https://javascript.info/formdata and https://www.npmjs.com/package/form-data.
My structure in Node is
Router.js file
return res.send(htmlFormTemplate({}));
});
router.post('/css',
[],
async (req, res) => {
let {data} = req.body;
///
result= do some calculation on {data}
///
return res.send(htmlFormTemplate({result}));
});
The htmlFormTemplate is a js file
module.exports = ({result}) => {
return `
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<form class="box" method ="POST">
<inputname="data" />
<button>Submit</button>
</form>
<script>
///tried form processing here
</script>
<section id="Results">
<ul><li>Your result is ${result}</li></ul>
</section>
</body>
</html>
`;
};
I'm self-taught and new so hope this makes sense and thanks for any help/ideas
You can check if the result variable is null before it gets to the section div:
${ result === null ? '' :
`<section id="Results">
<ul><li>Your result is ${result}</li></ul>
</section>`}
Like this, it wont show the result div if result if null.
There is a very simple to solve this problem,
just use some templating engine for ex EJS, its very easy to use and will help you better,
and your result is undefined because your using a promise and it might have happened that the response might have not come and you loaded the page. Just use await
return await res.send(htmlFormTemplate({result}));

Express JS does not perform delete

PUGJS script
form(id="form1" action="/delete" method="POST")
input(type="submit",name=+item['id'] value="delete")
My ExpressJS code
router.post('/delete', function(req, res, next) {
var id = req.params("i");
console.log("i am 0")
MongoClient.connect(url, function(err, db) {
console.log("i am 1")
db.collection('books', function(err, book) {
db.collection.deleteOne( {_id: new mongodb.ObjectID(id)} );
console.log("i am 2")
if (err) {
throw err;
} else {
db.close();
res.redirect('/');
}
});
});
});
Trying to perform a delete request but it does not even print ("i am 0")
can not determine what's broken with the code
NPM response POST /delete 404 7.247 ms - 1202
When you see a 404 the root cause is definitely how you set up the routing. This code would be successfully called if it is in app.js/server.js (or whatever your root express file is), but a 404 means that you have placed it in a secondary file and are using another path in there somewhere.
With that said, you also have an issue with how your route is defined if you want to read a route parameter (which is what the first line of your route handler tries to do).
router.post('/delete/:i', function...
The form itself isn't passing any id though through name (or id). You could either pass the id through the url called:
action= "/delete?id=" + id
...and read this in your route handler using req.query.id or you could insert a hidden input in the form and read it using req.body.id.
Also, the form name attribute has been deprecated and should be replaced with id.
Then, it's important to note that pug is highly dependent on indentation. Your code as pasted will generate an empty form and a separate input field.
This:
form(id="form1" action="/delete" method="POST")
input(type="submit",name=+item['id'] value="delete")
Generates this HTML:
<form id="form1" action="/delete" method="POST"></form>
<input type="submit" name="itemId" value="delete">
If you change the pug template to this (note the two additional spaces on the input line):
form(id="form1" action="/delete" method="POST")
input(type="submit",name=+item['id'] value="delete")
You will get this, which should work as expected:
<form id="form1" action="/delete" method="POST">
<input type="submit" name="itemId" value="delete">
</form>
Then, there's the problem in your delete function where you're missing a callback.
db.collection.deleteOne( {_id: new mongodb.ObjectID(id)} );
You need to either add a promise or callback here otherwise your code will move straight to close the connection.

Cannot delete mongodb entry with node and handlebars

I tried various ways to delete a entry but no luck. I know I'm close. I did use "post" instead of "delete" with no luck. I did the action request on the html, no luck. Im in a pickle :(
My routers:
router.delete('/:id',function(req, res){
Docket.findById(req.params.id, function(err, docket){
docket.remove(function(err){
res.redirect('/dockets');
});
});
});
Handlebars:
<form name="create-docket-form" id="create-docket-form" method="post">
<div class="form-submit">
<input type="submit" name="delete" value="Delete my docket" />
</div>
</form>
In your form, you are using method method="post", but your route is listening for DELETE requests: router.delete('/:id',function(req, res){ So this router is never triggered because the app can't found the route.
I wonder, how do you send your requests, but in if you are using no JavaScript code, you can work around this by applying approach from this answer.
I did solve this problem, first, you have to change the "delete" to "get" in the "router.get()", after that, you go to HandleBars file and put a tag 'button' inside the tag '', put the 'href: '/adress/{{variable to delete}}', go to your node.js and prepare the route, now I'll show you my code:
NODE.EXPRESS / .JS:
app.get(`/del-comander/:comand`,express.json() ,(req,res)=>{
let comanderDel = req.params.comand
Comander.deleteOne({comander: comanderDel}).then(()=>{
console.log(`deleted: ${comanderDel}`)
res.redirect('back')
}).catch((err)=>{
res.send(err)
})
}),
HANDLEBARS:
{{#each comanders}}
<strong> comander: </strong>{{comander}} <br>
<strong> skill: </strong>{{skill}} <br>
<strong>season: </strong>{{season}} <br>
<a href='/del-comander/{{comander}}'><button>delete</button></a>
<br>
<hr>
{{/each}}
OBS: the args inside '{{}}' was connected with the DataBase, I also did more than just delete the data and printed it to the screen, so each data could be deleted separately, I do not know if my answer was good, but somebody else could have this same problem if you want more code just ask.

textbox can't get focus in Node.js

I have a textbox in my site that can't seem to get focus. I tried adding focus on click with jQuery but that seems to have no effect. Can anyone help me out?
App link: http://test-app-andrew.herokuapp.com/
Jade:
div(id="templates",class="sideBarContent")
div(id="addPageBox")
input(type="text",id="addPage")
HTML(output from above):
<div id="templates" class="sideBarContent">
<div id="addPageBox">
<input type="text" id="addPage">
</div>
</div>
Coffeescript:
$ ->
$('input#addPage').click ->
$('input#addPage').focus()
Javascript (output from above):
// Generated by CoffeeScript 1.8.0
(function() {
$(function() {
return $('input#addPage').click(function() {
return $('input#addPage').focus();
});
});
}).call(this);
Any help would be great, thanks!

Resources