EJS check if status is 200 - node.js

I am looping over an array of objects, these objects contains links to images. Some of these images return with status 403 and do not display.
Here is what I have in ejs
<% Recipes.forEach(recipe => { %>
<div class="basis-2/12 min-w-max">
<% if (recipe.image) { %>
<img class="w-60 h-40 object-cover bg-slate-100 rounded-xl" src="<%= recipe.image %>" />
<% } else { %>
<img class="w-60 h-40 object-cover bg-slate-100 rounded-xl" src="/images/placeholder.png" /> <% } %>
</div>
<% }) %>
The if (recipe.name) itself only check whether there is a link or not, which is always true.
How should I go for this?

This solution works, the recipe.image (in this case) must have a value of null

You'd have to actually fetch the image on the server before rendering the page, which would slow down the loading.
If using JavaScript on the client side is possible, consider implementing the fallback there. See for example this answer: https://stackoverflow.com/a/1588899/240963
<img
src="<%= recipe.image %>"
onerror='this.onerror = null; this.src="/images/placeholder.png"'
/>
Alternatively you could implement a proxy on the server, and serve the fallback in case the image on the origin is not found; useful package for this is for example: https://github.com/http-party/node-http-proxy

Related

Node ejs forEach causing a 'Content Security Policy' error

I'm so excited to post my first Stack Overflow query. :D
I recently started a Node.js course and with that, I just want to point out I'm not doing any hardcore stuff just yet.
I have a local node server running with nodemon. I started working with ejs and discovered that a forEach loop is melting my web page for some reason.
I tried doing research and sifting through my code removing certain parts piece by piece that weren't there before the issue until the issue went away and discovered that when I take the forEach loop out of my code in my ejs file, the problem goes away.
//this is my .js file located in my ./routes folder
const express = require('express');
const router = express.Router();
const admin_data = require('./admin');
router.get('/', (req, res, next) => {
const products = admin_data.products;
res.render('shop', {
page_title: 'Shop',
prods: products
});
});
//nothing too hectic.
//this is my ejs file located in my ./views folder.
<% if (prods.length > 0) { %>
<div class="grid">
<% forEach (var products in prods) { %> //if i remove this and it's closing '}' it works fine.
<article class="card product-item">
<header class="card__header">
<h1 class="product__title">product</h1>
</header>
<div class="card__image">
<img src="" alt="A Book">
</div>
<div class="card__content">
<h2 class="product__price">$19.99</h2>
<p class="product__description">A very interesting book about so many even more interesting things!
</p>
</div>
<div class="card__actions">
<button class="btn">Add to Cart</button>
</div>
</article>
<% } %>
</div>
<% } %>
I expect the code to render the page but instead receive an error:
"SyntaxError: Unexpected token { in C:\Users\Ruan
Buitendag\Documents\NodeJS\Practice Server\views\shop.ejs while
compiling ejs" in my vscode terminal and "Content Security Policy: The
page’s settings blocked the loading of a resource at inline
(“default-src”)" in my browser console.
EDIT: PS. I tried running the page in firefox developer edition, plain firefox and google chrome.
I think the problem is in your loop. Use forEach this way:
<% prods.forEach(function(product) { %>
<article class="card product-item">
<header class="card__header">
<h1 class="product__title">product</h1>
</header>
<div class="card__image">
<img src="" alt="A Book">
</div>
<div class="card__content">
<h2 class="product__price">$19.99</h2>
<p class="product__description">A very interesting book about so many even more interesting things!</p>
</div>
<div class="card__actions">
<button class="btn">Add to Cart</button>
</div>
</article>
<% }) %>
Alternatively you can use for...of loop like this:
<% for (var product of prods) { %>
...

Node.js pass a value to a partial view

I have a route that looks like this:
app.get('/Search', function (req, res) {
var searchString = req.query.SearchString;
var request = require('./cstapi')(searchString, onBody);
function onBody(body) {
res.render('index', { output: body });
}
});
and an index.ejs that looks like this:
<div id="searchDiv">
<% include ../partials/search %>
<br>
<% include ../partials/results %>
</div>
search looks like this:
<form action="./search" method="GET">
<input type="text" name="SearchString" class="form-control" >
<input type="submit" value="Search" class="form-control">
</form>
and results looks like this:
<p>Search returned the following: <%= output %></p>
I'm trying to get the search results to display in a partial view after the user submits the form. With the above I get output is not defined when attempting to render index and the subsequent partial views.
I found a work around although I'm not 100% sure this is the best way of doing it:
By adding 'null check' to output in index I can avoid the output not defined error when accessing the results partial without search results.
So index now becomes:
<div id="searchDiv">
<% include ../partials/search %>
<br>
<%if (typeof output !== 'undefined') { %>
%> <% include ../partials/results %>
<% } %>
</div>
Hopefully someone can provide a better way?

How to check if Being edited on CMSDESK

I'm new to ASP and definitely new to Kentico. but i am fairly moving along.
Anyway. i am building this layout where there is a hidden div element:
<div style="display: none;">
<cms:CMSWebPartZone ZoneID="someContentZoneHere" runat="server" />
</div>
The problem with this script is that is does not show the Web Part Zone on the Design Page and i cannot add a Data inside it. Si i need to remove the style only when it is on the CMSdesk.
i have been thinking to use if else to solve the problem, but i do not know what to compare?
<% if(site is not in CMSDESK || CMSSITEMANAGER) { %>
//with style attribute
<div style="display: none;">
<% }else{ %>
//no style attribute
<div>
<% } %>
or are there any other ways to do this.
The condition you are looking for is:
if(CMS.PortalEngine.PortalContext.ViewMode != CMS.PortalEngine.ViewModeEnum.Edit &&
CMS.PortalEngine.PortalContext.ViewMode != CMS.PortalEngine.ViewModeEnum.Design)
You can also do it the other way round and check for CMS.PortalEngine.ViewModeEnum.LiveSite. Check the full list of possible values.

Loop and random photo generator -- not generating random photos

I'm looping through users (with Express.js) and displaying cards for them. For the users without profile pictures, I'm using the random photo generator at http://lorempixel.com/. It pulls a random photo every time:
<% users.forEach(function(user) { %>
<div class="user">
<div class="user-container">
<div class="img-container">
<!-- Image User -->
<div class="img-user" id="<%= 'img-div' + user.id %>">
<% var picture = user.get("profilePictureMedium");
if (picture) { %>
<img id="<%= 'img-' + user.id %>" src="<%= user.get("profilePictureMedium").url() %>" width="220"
/>
<% } else { %>
<img id="<%= 'img-' + user.id %>" src="http://lorempixel.com/g/220/220/animals/" width="220" >
<% } %>
<!-- /Image User -->
What's happening is that the same photo is generated for every user without a profile photo. However, if I manually load http://lorempixel.com/g/220/220/animals/ into a browser window I'll get a different photo everytime.
I stuck in:
<img src="http://lorempixel.com/g/220/220/animals/" width="220" />
Outside of the loop and it pulled the same photo as the photo in the loop, so I suppose the browser is catching the result of the first call.
Is there a way to avoid this caching so that it calls and retrieves a random photo each time?
One common solution is to append a redundant query string to the url. For example:
<img src="http://lorempixel.com/g/220/220/animals/?v=1404442966794" />
This random number could be the current timestamp or, perhaps better in this use case, the id for a given user, that way caching can still be utilized once an image has been acquired for a given user. i.e.
src="http://lorempixel.com/g/220/220/animals/?v=<%= user.id %>"

nodejs + ejs for if express returns a unexpected catch

im sure this is silly, but i cant get it to work for the life of me, i just want to do a simple for statement with an if inside on ejs, but it keeps returning a unexpected catch event in express.
to set up the scene, i've got a JSON thats setting up a a registration form in nodejs using ejs as my template renderer, lets say I have the following code:
var userData:{
"username":"User name",
"email":"johndoe#gmail.com",
"password":"Please enter Password",
"birthdate":"date"
}
and i have a ejs file that goes
<h1 id="page-title"><%= title %></h1>
<div id="list">
<form action="user/create/" method="post" accept-charset="utf-8">
<div class="item-new">
<% for (var key in userData){ %>
<% if(key != 'birthdate'){ %>
<input class="input" type="text" name="<%= key %>" placeholder="<%= userData[key] %>"/>
<% }else{ %>
//do something
<% } %>
</div>
i've tried to define a variable beforehand and check the value of the definitions
If the example you provided is indeed all of your code, you aren't closing all of your tags, specifically, you aren't closing your for loop, one of your divs, or your form. When I close all of these, the view will render for me without errors. This is the ejs that I used:
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style-min.css' />
</head>
<body>
<h1 id="page-title"><%= title %></h1>
<div id="list">
<form action="user/create/" method="post" accept-charset="utf-8">
<div class="item-new">
<% for (var key in userData){ %>
<% if(key != 'birthdate'){ %>
<input class="input" type="text" name="<%= key %>" placeholder="<%= userData[key] %>"/>
<% } else{ %>
<% } %>
<% } %>
</div>
</form>
</div>
</body>
</html>
And I used this function to render it:
exports.test = function(req, res){
res.render('test', { title: 'nodejs + ejs for if express returns a unexpected catch', userData:{
"username":"User name",
"email":"johndoe#gmail.com",
"password":"Please enter Password",
"birthdate":"date"
}});
};
When I use the above I get this as a result:

Resources