Reference Error on Index Page with Twitter Cards EJS - node.js

I have the following code in my header.ejs file for my Twitter card.
<head>
...
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="#DrDenverHBubble">
<meta name="twitter:creator" content="#DrDenverHBubble">
<meta name="twitter:title" content="<%= blog.title %>"></meta>
<meta name="twitter:image" content="<%= blog.image %>"></meta>
</head>
...
On my show.ejs page, my webpage display correctly and the Twitter card displays correctly as well on Twitter.
However, on my index.ejs page, I get the following error with the below code
ReferenceError: /home/ubuntu/workspace/drdenver/views/blogs/index.ejs:1
>> 1| <% include ../partials/header %>
2|
3|
4|
/home/ubuntu/workspace/drdenver/views/partials/header.ejs:16
14| <meta name="twitter:site" content="#DrDenverHBubble">
15| <meta name="twitter:creator" content="#DrDenverHBubble">
>> 16| <meta name="twitter:title" content="<%= blog.title %>"></meta>
17| <meta name="twitter:image" content="<%= blog.image %>"></meta>
18| </head>
19| <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
blog is not defined
Here is the index.ejs code
<% include ../partials/header %>
<div id="blog-index" class="container">
<div class="row" style="display: flex; flex-wrap:wrap;">
<div class="col-lg-12">
<% if(noMatch !== null) { %>
<h4> <%= noMatch %> </h4>
<% } %>
</div>
<% blogs.forEach(function(blog){ %>
<div class="col-lg-12">
<div class="ui medium rounded items">
<div class="item">
<div class="image">
<img src="<%= blog.image %>">
</div>
<div class="content">
<a class="header" href="/blogs/<%= blog._id %>"><%=blog.title%></a>
<div class="meta">
<span><%= blog.created.toDateString() %></span>
</div>
<div class="extra">
<% if(blog.body && blog.body.length > 0) { %>
<p><%- blog.body.substring(0, 120) %> ... </p>
<% } %>
Read More
</div>
</div>
</div>
</div>
</div>
<% }) %>
</div>
...
I am a new coder, but I understand that I am not passing anything into the variable blog which is causing my error. My solution was to on the show page remove the <% include ../partials/header %> and insert the header code with twitter card code and in the header.ejs page remove the Twitter card code. Is there a more DRY way of coding this?
Thanks

Your problem is, You are including header.ejs file which needs blog data. But you are not passing blog data to it. Change your include line to following
<%- include('../partials/header', {blog: blog}); %>

Related

SyntaxError: missing ) after argument list can't seem to find possible solution

What is the issue, Where did I go wrong? This is the code for index.ejs i made minor changes to my previous old_index.ejs. i have been struggling with this issue and the backend does have await function for calling aleph-js (aleph.im) so i don't think it's any issue about async.
**strong text**<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-3 rooms-sidebar">
<div class="card no-outline">
<div class="card-body">
<small>Logged in as</small><br>
<b>
hook this up later<br>
</b>
</div>
</div>
<hr>
<hr>
<div class="card no-outline mb-2 room-card">
<div class="card-body">
<span class='name'>
Chat
</span><br>
<span class='member-count'>
<small>
99 Members
</small>
</span>
</div>
</div>
</div>
<div class="col-9">
<div class="chat-room">
<nav class="navbar navbar-light">
<span class="navbar-brand" href="#">
<b>
Chat
</b>
</span>
<small>
99 Members
</small>
</nav>
<div id="messages">
<% posts.forEach((post)=> { %>
<% var parsed_item=JSON.parse(post.item_content) %>
<div class="message mb-2">
<div class="content-container">
<div class="content">
<%= parsed_item.content.body %>
</div>
<div class="author">
<%= parsed_item.address %>
</div>
</div>
</div>
<% }) %>
</div>
<div class="chat-box">
<form action="/messages" method="post" id='message-form'>
<div class="input-group">
<input type='text' name="message" id="message" cols="30" rows="10" class="form-control">
<div class="input-group-append"></div>
<input type="submit" value="Post Message" class="btn btn-primary">
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<%= posts %>
<script type='text/javascript'>
$(document).ready(() => {
const socket = new WebSocket('wss://api2.aleph.im/api/ws0/messages?msgType=POST&contentType=chat')
socket.onmessage = (e) => {
let message = JSON.parse(e.data)
console.log(message)
let content = message.content.content.body;
$('#messages-list').prepend(`<li>${content}</li>`)
}
$('#message-form').submit((e) => {
e.preventDefault();
$.post('/messages', $('#message-form').serialize())
$('#message-form textarea').val('')
})
})
</script>
</body>
</html>
<%= 'me' if message.user == current_user %>
Refer The Image

how can i send data without reloading form node js and ejs

there. I am creating a blog website and I want to post some comments on that post. but the form is reloading am not getting data to store MongoDB. I search on the internet so I got ajax but ajax is not working and this is new for me. help me out with this problem. I am using node js and ejs templating and MongoDB.
node js code
app.post("/do-comment", async (req,res) =>{
const comment = new Comment({name:req.body.name,comment:req.body.comment});
await comment.save();
await Blog.findOneAndUpdate({_id:req.body._id}, {$push: {comment}});
res.send("Comment was added successfully");
})
HTML code
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Blogs</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src=
"https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js">
</script>
<!-- CSS only -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<!-- JavaScript Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-primary">
<div class="container-fluid">
<a class="navbar-brand" href="#">Blogs</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarTogglerDemo02" aria-controls="navbarTogglerDemo02" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarTogglerDemo02">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/compose">compose</a>
</li>
<li class="nav-item">
<a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>
</li>
</ul>
<form class="d-flex">
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
</div>
</div>
</nav>
<div class="container">
<div class="col">
<img src="data:image/<%=post.image.contentType%>;base64,
<%=post.image.data.toString('base64')%>" alt="photo"width="1000px" height="500px" alt="photu">
<h1><%= post.title %></h1>
<p><%= post.content %></p>
</div>
<div class=''>
// form is here for comment
<form method="POST" onsubmit="return doComment(this);" class="theme-form-one">
<input type="hidden" name="_id" value="<%=post._id %>">
<div class="row">
<div class="col-md-6 col-12"><input type="text" name="name" placeholder="Name"></div>
<div class="col-12"><textarea name="comment" placeholder="Comments"></textarea></div>
</div>
<button class="theme-button-one">POST COMMENT</button>
</form>
</div>
//// catching comments here
<div class="">
<div class="container-fluid">
<% data.forEach(function(cData){ %>
<h1><%= cData.name %></h1>
<p><%= cData.comment %></p>
<% }) %>
</div>
</div>
</div>
//js code here
<script>
function doComment(form){
$.ajax({
url:"/post/do-comment",
method:"POST",
data:{name:form.name.value,comment:form.comment.value,
_id:form._id.value},
success: function(response){
alert(response);
}
});
return false;
}
</script>
</body>
</html>

How to check in layout if user is logged in

Like in title.
I have layout:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
<link
rel="stylesheet"
href="https://bootswatch.com/4/journal/bootstrap.min.css"
/>
<title>Node.js & Passport Login App</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarColor03" aria-controls="navbarColor03" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarColor03">
<ul class="navbar-nav mr-auto">
<form class="form-inline my-2 my-lg-0">
<input class="form-control mr-sm-2" type="text" placeholder="Search">
<button class="btn btn-secondary my-2 my-sm-0" type="submit">Szukaj!</button>
</form>
<li class="nav-item active">
<a class="nav-link" href="/index">Strona Główna
<span class="sr-only">(current)</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">O nas</a>
</li>
</ul>
<ul class="navbar-nav">
<li class="nav-item">
<%if (!isLoggedIn) { %>
<div> <a class="nav-link" href="/users/logout">Wyloguj</a></div>
<% } %>
<%if (isLoggedIn) { %>
<div> <a class="nav-link" href="/users/login">Zaloguj</a></div>
<% } %>
</li>
</ul>
</div>
</nav>
<div class="container"><%- body %></div>
<script
src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
crossorigin="anonymous"
></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js"
integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut"
crossorigin="anonymous"
></script>
<script
src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js"
integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k"
crossorigin="anonymous"
></script>
</body>
</html>
and some routes like e.g register view,where I check if user isLogged(no way to registration) etc.
router.get('/register', (req, res) =>
res.render('register',{isLoggedIn:isLoggedIn()}));
I have 2 problems:
1)<%if> in my layout doesn't work (i don't know why)
2)How to inject state of user (logged or not) to layout? I don't want to repeat all of the code from layout on my views.
I think you have swapped the login/logout elements. For !isLoggedIn should be Zaloguj, for isLoggedIn should be Wyloguj.
Generally, I attach to render some (not all, as it can contain pasword hashes) user data res.render(‘register’, { user }) You will need them either, you will want to display logged in user name or so.
Then:
<% if (user) { %>
<h2><%= user.name %></h2>
<% } %>
If you have a part of ejs you want to have in other templates, just use includes:
<div id=“parent_div”>
<div id=“register_div”>
<% include('register.ejs') %>
</div>
<div id=“mainbody_div”>
<% include('body.ejs') %>
</div>
<div>
I solved my problem - thanks to #Fide for show me a way where is a bug!
router.get('/register',
function (req,res){
res.render('register', {user: req.User} )
});
I have to take User from req - simple but I spent a lot of time on it!

Issue while using ejs syntax

This is my ejs file(_post.ejs):
<link rel="stylesheet" href="/css/home.css">
<div id="home-container">
<% if(locals.user){%>
<section id="feed-posts">
<h4>Posts</h4>
<form action="/posts/create" method="post" id="new-post-form">
<textarea name="content" cols="30" rows="3" placeholder="Type here..." required></textarea>
<input type="submit" value="Post">
</form>
</section>
<%}%>
<section id="posts-wall" >
<ul>
<% for(post of Posts){ %>
<%- include('_post') -%>
<hr>
<% } %>
</ul>
</section>
<section id="user-friends">
<h4>Friends</h4>
<% for(u of all_users){%>
<p>
<%= u.username %>
</p>
<%}%>
</section>
</div>
<script src="/js/home_posts.js"></script>
Error :
Error: /Users/nishantbhatia/Desktop/nodews/codial/views/home.ejs:17
15| <ul>
16| <% for(post of Posts){ %>
>> 17| <%- include('_post') -%>
18| <hr>
19| <% } %>
20| </ul>
I have included the closing tags as well. Really not sure abt the error. Any help would be appreciated.I tried to read the documentation still no clue.
The syntax should be ,remove - from closing tag. See the docs
<section id="posts-wall" >
<ul>
<% for(post of Posts){ %>
<%- include('_post') %>
<hr>
<% } %>
</ul>
</section>

MEAN + Passport: login failed, don't redirect just show an error in the same modal

Just like in the question: how can I use Passport without redirecting user to the /signin or /home when he fails his authentication?
To login user has to click on "login" button, a modal will pop up, he fills the data. If he succeeds he is redirected to the homepage. But if he isn't I want to show him the flash message in the same modal without redirecting. It kinda works because if you fail to login and click "login" again the error message will be shown. But I don't want to force users to constantly click it to check what went wrong.
They should fail, see the error, fill in new data and click submit again.
home.server.route.js:
var user = require(__dirroot + '/app/controllers/user.server.controller.js')
var passport = require('passport')
module.exports = function(app) {
var home = require(__dirroot + '/app/controllers/home.server.controller.js')
app.get('/', home.render)
app.route('/home/signin')
.get(user.renderSignin)
.post(passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/',
failureFlash: true
}))
}
home.server.controller.js:
exports.render = function(req, res) {
res.render('home', {
title: 'erpeg',
messages: req.flash('error') || req.flash('info'),
srvuser: req.user ? req.user : null,
cltuser: JSON.stringify(req.user)
})
}
home.ejs:
<!doctype>
<html>
<head>
<title></title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="lib/foundation/css/normalize.css">
<link rel="stylesheet" href="lib/foundation/css/foundation.css">
<script src="https://www.google.com/recaptcha/api.js"></script>
<script src="lib/jquery/dist/jquery.min.js"></script>
</head>
<body>
<nav class="top-bar">
<ul class="title-area">
<li class="name">
<h1>
<a href="/">
<%= title %>
</a>
</h1>
</li>
<li class="toggle-topbar menu-icon">
<a href="#">
<span>Menu</span>
</a>
</li>
</ul>
<section class="top-bar-section">
<ul class="right">
<% if (srvuser) { %>
<% if(srvuser.rank == "administrator") { %>
<li>
</li>
<% } %>
<li>
<a href="/profile">
<%= srvuser.fullName %>
</a>
</li>
<li>
wyloguj
</li>
<% } else { %>
<li>
rejestruj
</li>
<li class="active">
zaloguj
</li>
<% } %>
</ul>
</section>
</nav>
<div id="signinModal" class="reveal-modal" data-reveal aria-labelledby="signinTitle" aria-hidden="true" role="dialog">
<% for (var i in messages) { %>
<div data-alert class="alert-box warning">
<p>
<%= messages[i] %>
</p>
×
</div>
<% } %>
<h1 id="signinTitle">logowanie</h1>
<form action="/home/signin", method="post">
<div class="row">
<div class="large-12 columns">
<input type="text" name="username" id="username" placeholder="nazwa użytkownia">
</div>
</div>
<div class="row">
<div class="large-12 columns">
<input type="password" name="password" id="password" placeholder="password">
</div>
</div>
<div class="row">
<div class="large-12 columns">
<input class="button expand" type="submit" value="zaloguj">
</div>
</div>
</form>
</div>
<script src="lib/modernizr/modernizr.js"></script>
<script src="./lib/foundation/js/foundation.min.js"></script>
<script src="lib/angular/angular.min.js"></script>
<script src="lib/angular-route/angular-route.min.js"></script>
<script src="lib/angular-resource/angular-resource.min.js"></script>
<script src="/user/user.client.module.js"></script>
<script src="/user/services/authentication.client.service.js"></script>
<script src="/game/game.client.module.js"></script>
<script src="/game/controllers/game.client.controller.js"></script>
<script src="/game/services/game.client.service.js"></script>
<script src="/game/config/game.client.route.js"></script>
<script src="application.js"></script>
</body>
</html>
PS: I had it working with separate pages but since I am changing my template engine from Jade to EJS I thought I will do it more elegantly (inside a modal). Any help?

Resources