How to conditionally show different UI in Jade? - node.js

I have the following template:
extends layout
block content
#wrapper
#logo
a(href='/')
p #{title}
#msg
| hi #{user}
#display
#register
----A registration form here----
#login
----A login form here-----
include footer
If the user opens this page via POST and I use a token to decide if he is logged in like so:
exports.home = function(req, res) {
// if user is not logged in, show both login and register forms
if (typeof req.session.username == 'undefined') {
res.render('home', { title: 'Online Coding Judge'});
}
// if user is logged in already, just say hi to him
else {
// what here???
}
};
How do I show different things on the page depending on whether he logged in or not?
EDIT: A more realistic example would be to show an error message if there was a failed login in the same UI I would need to conditionally show an error message.

Something like this should work:
EDIT: revised:
block content
#wrapper
#logo
a(href='/')
p #{title}
if {user}
#msg
| hi #{user}
#display
#register
----A registration form here----
#login
----A login form here-----
else
--- some other logic ---
include footer

Related

Pass data to the same page in express

i want to pass data from server to the same page if there is an error in the POSTED data.
i have two routes , one route to display the contents and the other route for adding new content. i am using pug as view.
form for the new content is :
extends layout
block content
form(action="/create", method="POST")
h2= title
p
| Text :
input(type="text", name="text")
input(type="submit")
whenever i click the submit button the value in the input is posted
here's the node route.post() code :
router.post('/create' ,function(req,res,next){
if(req.body.text === ''){
res.send("empty")
}else{
contents.push(text: req.body.text )
res.redirect('/')
}
} )
currently if i submit the form without any input value , it will send "empty" msg in a blank page.
What I want is that if the input value is empty, rather than sending "empty" in a blank page i want to send "empty" msg to the same Form page and show anywhere.
like this :
thank you : ) ......
We must use a variable to indicate there is an error. For example:
View
extends layout
block content
form(action="/create", method="POST")
h2= title
p
| Text :
input(type="text", name="text")
input(type="submit")
h2= error
Controller
router.post('/create' ,function(req,res,next){
if(req.body.text === ''){
res.render("your_view_name_here", { error: "empty" })
}else{
contents.push(text: req.body.text )
res.redirect('/')
}
})

Button in Node.js project works properly after two clicks not one

I'm making a simple project with node.js, express, mongodb, express session etc. It is a travel type site and a user in the database has a username, password and a list of destinations he wants to go to. Each destination page has a button to add that destination to the list and there is also a page which shows the current user's list. The proper functionality is that on the first button press the destination should be added to the users list in the database and the ejs view for the list page should be updated and on the second button press an alert should come up saying that the current destination is already on the user's list. However, seemingly randomly the button sometimes only works properly after two button presses and the alert and ejs view update of the list page occur on the third button press. Here are some code snippets:
This is my get request for the list page where I pass the current session user's want to go list as a parameter:
function isAuthenticated (req, res, next) {
if (req.session.user) next()
else res.redirect('/');
}
app.get('/wanttogo',isAuthenticated,function(req,res){
res.render('wanttogo',{dests:req.session.user.wantgo})
});
I update this list both in the session and in my database in each page's post request. This is an example for one of the pages:
app.post('/inca',function(req,res){
if((req.session.user.wantgo.length === 0) || !(req.session.user.wantgo.includes("Inca Trail to Machu Picchu"))){
req.session.user.wantgo.push("Inca Trail to Machu Picchu");
req.session.save();
db.collection("myCollection").updateOne({username:req.session.user.username},{$set:{wantgo:req.session.user.wantgo}});
db.collection("myCollection").findOne({username: req.session.user.username},(err,result)=>{
req.session.user.wantgo = result.wantgo;
req.session.user=result;
req.session.save();
});
}
else{
alert('This destination is already on your Want-To-Go List');
}
res.redirect('/inca');
and this is the part of the ejs view of the list page where I loop over the user's list and print it using the parameter I passed earlier:
<div>
<% for(var i=0; i < dests.length; i++) { %>
<h1><%= dests[i] %></h1>
<% } %>
</div>
Any help is appreciated!
This could be due to the fact "updateOne" and "findOne" are async functions and thus the database is not updated before you do the second button press.
Since this depends on time when the async operation is completed it sometimes works and sometimes doesn't.
Try using async await like this
app.post('/inca',async function(req,res){
if((req.session.user.wantgo.length === 0) || !(req.session.user.wantgo.includes("Inca Trail to Machu Picchu"))){
req.session.user.wantgo.push("Inca Trail to Machu Picchu");
req.session.save();
await db.collection("myCollection").updateOne({username:req.session.user.username},{$set:{wantgo:req.session.user.wantgo}});
await db.collection("myCollection").findOne({username: req.session.user.username},(err,result)=>{
req.session.user.wantgo = result.wantgo;
req.session.user=result;
req.session.save();
});
}
else{
alert('This destination is already on your Want-To-Go List');
}
res.redirect('/inca');

React Native Navigation - Component will not unmount even after using stackactions.reset

I am using react native with react-navigation v4
I have a home screen and a welcome screen. I am using redux to store the user that is logged in. In the welcome screen (before the user logs in), I reset the user to null like this:
useEffect(() => {
dispatch(updateCurrentUser(null));
});
On my home screen (after the user logs in), I navigate to the welcome screen with a logout button the following way:
<Button
title="Logout"
onPress={() => {
const resetAction = StackActions.reset({
index: 0,
actions: [
NavigationActions.navigate({routeName: "Welcome"}),
]
});
props.navigation.dispatch(resetAction);
// navigationData.navigation.pop();
// navigationData.navigation.navigate({routeName: "Welcome"});
}}
/>
After I run this, I get an error whenever i press the logout button
Since the user is now null and on the home screen I have the following code <Text style={styles.text}>Welcome, {currentUser.username}!</Text>, I am getting an error that null does not have the attribute username since currentUser is now null.
I do not understand why the home screen will not unmount and is being rendered when i reset the stack and navigated to the welcome screen. What could be the issue here?
You can just leave the stackaction and use switchnavigator and put these two screens in separate stacks. like
export default createAppContainer(createSwitchNavigator(
{
stack1:ScreenStack1,
App: AppTabs,
},
{
initialRouteName: 'AuthLoading',
}
));
so if I will navigation.navigate("App") from stack1 and at some point of time if I go back to stack1 from App navigation.navigate("stack1") here now all the screens of stack1 will behave like rendering fresh.

Passport local - Cannot read property 'email' of undefined

I am using Passport in my app. When I render views to display user information, I'm able to display user information (I'm using jade, btw) in that view:
#user
p #{user.fname} #{user.lname)
However, that view extends a layout, and in that layout, I am not able to access the user variable. My end goal is to have the nav bar in the layout and display a few user related items. I know I could set variables in my blocks, but I don't want to have to set them in every single view (that seems far more repetitious than it should be, and seems like the wrong way to do things). How can I make my user information available to my layout that my views extend and do it in one place?
layout.jade
...
#user
if(user != null)
ul.nav.navbar-right.navbar-nav
li.dropdown
a.dropdown-toggle(href='#', data-toggle='dropdown') #{user.email} <--BREAKS HERE
...
user.jade
extends layout
...
#user
h1.title Welcome #{user.email} <--WORKS FINE HERE
...
layout.jade
block header
#user
if(user != null)
ul.nav.navbar-right.navbar-nav
li.dropdown
a.dropdown-toggle(href='#', data-toggle='dropdown') #{user.email}
block content
or
layout.jade
block header
#user
if(user != null)
ul.nav.navbar-right.navbar-nav
li.dropdown
a.dropdown-toggle(href='#', data-toggle='dropdown')
| #{user.email}
block content
user.jade
extends layout
block content
#user
h1.title Welcome #{user.email}

How to know if block content is empty in Jade

How can we check if block is exist in Jade, I'm trying to make a template in Jade where in i have following block in layout.jade and in login.jade i have extended layout.jade. Now when in account.jade i will have both left and main content blocks
extend layout.jade
div(class='col-md-4')
block leftcontainer
div(class='col-md-8')
block content
Now in login.jade i want to hide
div(class='col-md-4')
block leftcontainer
and make the main content full page, if leftcontainer is not there. It should look like this
div(class='col-md-12')
block content
if user is on some page i want to hide left column block. Say if user is in login page then
If I got it right, you wan't to hide a block if a user (e.g. a user who is logged in to your app) is at a certain page. If this is right do something like this:
Example with Express & Passport:
// server
app.get('/login', function(req, res){
if(req.isAuthenticated()) {
res.render('login', { 'user' : req.user } );
} else {
res.render('login', { 'user' : null } );
}
});
// layout
extend layout.jade
if user !== null
div(class='col-md-12')
block content
else
div(class='col-md-4')
block leftcontainer
div(class='col-md-8')
block content
In general you can work with other conditional statements in Jade, without Passport, this was just an example. You may want to take a look at the reference, especially under conditional or case.

Resources