Making Variable Passed Through Pug Available to Javascript - javascript

I have a Pug view that gives a set of links to a user. Before you get to the page the user has already authenticated and I have the username and their department in session variables. I can pass them as variables to the view like this:
res.render('landingpage', { title: 'Landing Page',
username: req.session.username,
department: req.session.department });
And then in the view I have this line and it works:
p(class='navbar-text') Welcome #{username} from #{department}
which prints "Welcome Bob from Accounting" at the top with no problem.
But what I need to do is control whether some of the links are visible based upon the passed in department. (The department was discovered in the authentication function that passed the user onto the landing page and placed into the session.)
I was trying to place this into the document ready function but that doesn't work as it is undefined. What I need to do is to be able to change the visibility attribute and the onclick event for a link based upon the department. I have a JSON configuration file that tells me the departments allowed to access the link but I can't figure out how to translate that department variable into a javascript function that I can call to change the visibility.
I've tried to add it to a document ready function as department and #{department} but it just ends up either not knowing what it is or using it like the literal string. Any ideas of how to proceed?

Okay so I didn't post enough information for anyone to see what I was asking. Sorry. In the process of creating a new post and cutting it all down to just the part I needed I got it to work. This code works:
In the app.js file
'use strict';
var express = require('express');
var app = express();
app.set('views', './views');
app.set('view engine', 'pug');
var session = require('express-session');
var FileStore = require('session-file-store')(session);
var fileStoreOptions = {
path: './sessions',
ttl: 86400
};
var sessionOptions = {
secret: 'SecretKey',
resave: false,
saveUninitialized: false,
name: 'sessionId',
store: new FileStore(fileStoreOptions)
};
app.use(session(sessionOptions));
app.get('/landingpage', function(req,res,next) {
req.session.accessToken = true;
req.session.username = 'Bob';
req.session.department = 'Accounting';
res.render('landingpage', { title: 'Landing Page',
username: req.session.username,
department: req.session.department });
});
app.get('/images/DarkBlueIcon.png', function(req,res) {
res.sendFile(__dirname + '/images/DarkBlueIcon.png');
});
app.get('/node_modules/jquery/dist/jquery.min.js', function(req,res) {
res.sendFile(__dirname + '/node_modules/jquery/dist/jquery.min.js');
});
var server = app.listen(3000, function () { });
and this is in the pug file:
doctype html
html
head
title=title
script(src='/node_modules/jquery/dist/jquery.min.js')
body
p(class='navbar-text') Welcome #{username} from #{department}
img(id='accessApproved' src='/images/DarkBlueIcon.png' class='overlay' style='visibility: hidden;')
script.
$(document).ready( function() {
if('#{department}' === 'Accounting') {
document.getElementById('accessApproved').style.visibility = 'visible';
}
});
Gives you this:
screenshot of Hello to Bob and Blue Icon

To clarify from the other solutions: the interpolated string must be nested within quotation marks. If you don't use the quotation marks around the #{} then javascript tries to read it as a variable.
Solution:
'#{department}' === 'Accounting'
Explanation:
The solution evaluates to 'Accounting' === 'Accounting',which is true. The incorrect way would be to forget the quotes, and try #{department} === 'Accounting' which evaluates to Accounting === 'Accounting', which is the same as Undefined === 'Accounting', which is false.

You can use a hidden input to pass the department info and get the input's value in js.
Example:
doctype html
html
head
title=title
script(src='/node_modules/jquery/dist/jquery.min.js')
body
input#department(type='hidden',value=department)
p(class='navbar-text') Welcome #{username} from #{department}
img(id='accessApproved' src='/images/DarkBlueIcon.png' class='overlay' style='visibility: hidden;')
script.
$(document).ready( function() {
var department = $('#department').val();
if(department === 'Accounting') {
document.getElementById('accessApproved').style.visibility = 'visible';
}
});

Related

How to receive data from a button in a form?

This seems very simple but I can't figure it out. I am trying to get back the value of a button so I can conditionally render a page template. I can't seem to capture the value of the button though.
Here is my js code.
app.get("/trades", (req, res) => { // line 465
let button_value = req.params.value;
console.log(button_value);
// res.render("activate_pause")
});
And here is my html/ejs markup:
<form action="/trades" methods="get, post" name="groups_button">
<button class="orange" type="submit" name="frontpage_trades_button" value="pause">Pause Campaigns</button>
<button type="submit" name="frontpage_trades_button" value="enable">Activate Campaigns</button>
</form>
The values 'pause' or 'enable' will be used to set a status of true or false, which will render the desired template ( or so I hope!). Can anyone help??
methods is not a valid attribute of the <form> element
console.log('Is method in <form>?: ', 'method' in HTMLFormElement.prototype);
console.log('Is methods in <form>?: ', 'methods' in HTMLFormElement.prototype);
So the first thing to do is to replace methods with method and set only one method (I'd suggest POST).
Then in the Node.js code, make sure you have the proper middleware in order to decode URL encoded forms:
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true }));
This should allow you to retrieve the value of the clicked button, like this:
app.post("/trades", (req, res) => {
let button_value = req.body.frontpage_trades_button;
console.log(button_value);
// res.render("activate_pause")
});
u can use data attribute to take it
<button type="submit"id="x" name="frontpage_trades_button" data-value="enable">Activate Campaigns</button>
app.get("/trades", (req, res) => { // line 465
let button_value = req.params.value;
console.log($("#x").data("value"));
// res.render("activate_pause")
});

How to redirect user to a different path on the same domain with a click of a button in express?

I am creating a simple web app, and I want to be able to redirect a user to a different path in my project with a click of a button. I have two same versions of the website in english and polish. I am using express in node js and dynamic routing. And at the moment when I click the button it just adds the path on top of already existing path leading to nowhere. Forgive me if it's a rookie problem, I can't seem to figure out why it is happening.
My code in backend looks like this:
app.get("/stand/:lang/:id", function(req, res){
const requestedLang = req.params.lang;
const requestedId = req.params.id;
if (requestedLang === 'en' && requestedId === "1"){
res.render("stand1en");
} else if (requestedLang === 'pl' && requestedId === "1") {
res.render("stand1");
}
});
My front end and the buttons looks like this:
Polski
English
I would like to redirect them to the website on a click of the button. Any ideas?
You can use res.redirect in node.
You need to have 2 route :
1 that render the
"en" file
and 1 that render
"pl" file
You can use res.redirect function of expressjs which redirects to the URL derived from the specified path.
app.get("/stand/:lang/:id", function(req, res){
const requestedLang = req.params.lang;
const requestedId = req.params.id;
if (requestedLang === 'en' && requestedId === "1"){
res.redirect("link to the page1!");
} else if (requestedLang === 'pl' && requestedId === "1") {
res.redirect("link to the page2");
}
});
I think this will solve your problem.

Re-rendering an EJS template after jQuery POST request with new data

Update Edited my original code due to errors.
This is my first question posted here so please be gentle. :)
I am using node.js with Express and EJS forms.
What I am trying to achieve is to have an EJS template re-rendered after a jQuery POST request with new data. This is a simplified example of what I am trying to do (my original code includes a lot of fuss, SQL queries and is not properly refactored).
My goal would be to render the same template with different data when pressing a button on the page. What happening currently is when I press the button, the data is there (checking it in console), but the page does not render again with the new data. I am completely out of ideas and been stuck with this for almost a day now.
I know I could do something like
res.send(JSON.stringify(myData));
and build the HTML with a JS script, but it would be nice to be able to use EJS for better readability - my original code includes a lot of HTML elements.
Is it doable at all? Or is this an intended behaviour for rendering with Express? Sorry if I am being clueless, as I am fairly new to web development.
Anyway, here is my code, all ideas are greatly appreciated. Thanks!
test_dynamic.ejs:
<html>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form method="post" action="/test">
<wrapper>
<h1>
<button id="toggleButton" onclick="toggle()" type="button">Toggle</button>
</h1>
<div>
<% console.log('Should show ' + name + ' with id: ' + id) %>
<li><%=name %></li>
<li><%=id %></li>
</div>
</wrapper>
</form>
</html>
<script>
var shouldShowJohn = false;
function toggle () {
var postData = {};
shouldShowJohn = !shouldShowJohn;
if (shouldShowJohn)
postData.mode = 1;
else
postData.mode = 2;
$.post('http://localhost:3000/test', postData, function (data) {
$('#toggleButton').html('').append('Showing ' + postData.mode);
});
}
</script>
routes.js:
router.get('/test', (req, res) =>{
var obj = {
name: 'DefaultName',
id: 1
}
res.render('test_dynamic', obj);
})
router.post('/test', (req, res) => {
var obj = {};
console.log('req.body.mode: ' + req.body.mode);
if (req.body.mode == 1)
obj = {
name: 'John',
id: 2
}
else
obj = {
name: 'Karl',
id: 3
}
res.render('test_dynamic', obj)
})
Please take a look at the example I've included via link below. There is a lot wrong with your HTML above, but I will focus on your question. There are several ways you can solve this problem so this is the simplest.
As stated in my comment, the workflow is:
Send POST
Respond with success/failure
If success, redirect/re-request same page from server.
Note I am not addressing EJS because when you request the page from the server that will happen naturally as you have laid out above.
Step 1: So in the sample, index.js is the server, I have basic routing to two files, index.html and page2.html. I did this so you can see the change happening. Next, in the index.html file I have a button that generates the POST request via jQuery. This takes care of step 1.
Step 2: index.js accepts the post request to /test and responds with a simple string "success" (you could respond with anything)
Step3: In index.html the $.post() handler tests for the string 'success' and the redirects to page2.html. In your scenario this would redirect back to the same page. I made it different so you could realize the change easily.
Solution
https://repl.it/#randycasburn/SimplePostResponseRedirect
Here is my solution, partially based on Randy's answer.
test_dynamic.ejs:
<html>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body id="myBody">
<form method="post" action="/test">
<wrapper>
<h1>
<button id="toggleButton" onclick="toggle()" type="button">Toggle</button>
</h1>
<div>
<% console.log('Should show ' + name + ' with id: ' + id) %>
<li><%=name %></li>
<li><%=id %></li>
</div>
</wrapper>
</form>
</body>
</html>
<script>
var shouldShowJohn = false;
var postData = {};
postData.mode = 'toggle';
function toggle () {
$.post('http://localhost:3000/test', postData, function (data) {
$('#toggleButton').html('').append('Showing ' + postData.mode);
$('#myBody').html(data);
});
}
</script>
routes.js:
router.get('/test', (req, res) =>{
var obj = {
name: 'DefaultName',
id: 1
}
res.render('test_dynamic', obj);
})
var currentMode = 1;
router.post('/test', (req, res) => {
var obj = {};
console.log('req.body.mode: ' + req.body.mode);
if (req.body.mode == 'toggle')
if (currentMode < 3)
currentMode++;
else
currentMode = 1;
if (req.body.mode == 1)
obj = {
name: 'John',
id: 2
}
else
obj = {
name: 'Karl',
id: 3
}
res.render('test_dyanmic', obj)
})

Proper display of user editing form (CRUD model) with checkbox

I'm making a simple CRUD model with input checkbox. I have no problems on server side, everything is fine. I use NodeJS +MongoDB. But I have problem in editing existing user. When I edit an existing user with a checked checkbox( I get JSON object with parameter checked=true ) how should I display it using JS? This is part of my users.js file in /routes/ folder
var express = require('express');
var router = express.Router();
var User = require('../../models/User');
var rest = require('restler');
router.get('/adduser', function(req, res){
var user = new User();
user.contacts.push({phone: '', email: ''});
rest.get('http://localhost:3000/api/adduser').on('complete', function(data) {
res.render('users/add', { title: 'Add New Users' , n: user});
});
});
And this is views/users/fields.jade part of file for better understanding:
.form-group
label.col-sm-2.control-label(for='email') E-mail:
.col-sm-10
input(type="email", placeholder="email", name="email", value = n.contacts[0].email,required)
.form-group
.col-sm-offset-2.col-sm-10
input#enabled(type="checkbox",style='text-align: center; vertical-align: middle;',placeholder="", name="enabled", value = n.enabled)
| Enable user
So my problem is that I don't understand how I should display that checkbox is really checked when loading existing user.
If user is checked attribute n.enabled=true and if not n.enabled=false. So if user is checked on load of that user I need the input filed to be checked.
I've tried it to do the following way, but it wrote me that n wasn't defined...and I don't know how to pass n as the parameter for that function:
$(document).ready(function(){
if(n.enabled=="true"){$("enabled").toggle(this.checked);}
});
In fields.jade, change value = n.enabled to checked = (n.enabled ? 'checked' : '')
Use # for id-selectors and use n.enabled directly to hide or show your element like,
$("#enabled").toggle(n.enabled);
//-^ prepend # before id selectors
toggle() will show/hide your element, To check uncheck use the prop() like
$(document).ready(function(){
$("#enabled").prop("checked",n.enabled);
});

passing data between server and client (node.js + mongodb)

I'm working with node.js express and mongodb, I have a input data from client, I need to pass the data to server look for its property and send to the client in another page.
Now I have problem with req.body.age that suppossed to get the data from client's input and use find() to get its appropriate property.
Server side code:
functions are routed in another .js file
exports.find_user = function(req, res) {
res.render('find_user.jade');
};
exports.user = function(req, res){
member = new memberModel();
member.desc.age = req.body.age; //problem
console.log(req.body.age); //undefined
memberModel.find({desc: {age: '7'}}, function(err, docs){
res.render('user.jade', { members: docs });
console.log(docs);
});
};
memberModel.find({desc: {age: '7'}} just hardcode picking up user with age 7 (works)
client side code (jade):
page for data input:
find_user.jade
form(action='/', method='post')
fieldset
lable(for="age") Find user by age:
input(type="text", size="30", name="age", required="required")
input(type='button', value='Find', onclick='location.href=\'find_user/user/\'')
page for data output with its property:
user.jade
tr
th Name
th Age
tbody
- members.forEach(function(member){
tr
td= member['name']
td= member['desc']
- });
You are not submitting your data in find_user.jade file when the user clicks the button. Instead, the client is only redirected to another page.
This is how your find_user.jade file should look like:
form(action='find_user/user/', method='post')
fieldset
label(for="age") Find user by age:
input(type="text", size="30", name="age", required="required")
input(type='submit', value='Find', name="submit")

Categories