express can't serve static file for child ejs file - express

express version is 3.2.5, ejs version is 0.8.4
I want to serve stylesheets/style.css
I am doing this way in app.js
app.use(express.static(path.join(__dirname, 'public')));
app.use(app.router);
// render article.ejs
app.get('/u/:name/:day/:title', function(req,res){
Post.getOne(req.params.name, req.params.day, req.params.title, function(err, post){
if(err){
req.flash('error',err);
return res.redirect('/');
}
res.render('article',{
title: req.params.title,
post: post,
user: req.session.user,
success: req.flash('success').toString(),
error: req.flash('error').toString()
});
});
});
my structure is header.ejs
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Blog</title>
<link rel="stylesheet" href="stylesheets/style.css">
</head>
<body>
article.ejs content is
<%- include header %>
<p class="info">
author:<%= post.name %> |
date:<%= post.time.minute %>
</p>
<p><%- post.post %></p>
<%- include comment %>
<%- include footer %>
When I access http://localhost:3000/
GET /stylesheets/style.css 304 9ms
while access localhost:3000/u/username/date/postname
GET /u/username/date/stylesheets/style.css 404 10ms
why it shows this /u/username/date/stylesheets/style.css directory
Any ideas?

You don't start your stylesheets path with a /. So it's loading "stylesheets/style.css" relative to whichever HTML file requested it.

Related

I got 'is not defined' when trying to access class from a CDN loaded on Vue js

While trying to use Twilio TaskRouter JS SDK on Vue JS, that you have load through CDN.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
<script src="https://sdk.twilio.com/js/taskrouter/v1.21/taskrouter.min.js" integrity="sha384-5fq+0qjayReAreRyHy38VpD3Gr9R2OYIzonwIkoGI4M9dhfKW6RWeRnZjfwSrpN8" crossorigin="anonymous"></script>
</body>
</html>
I want to init my worker like this:
export const initWorker = (token) => {
return new Twilio.TaskRouter.Worker(token);
}
but it's giving me this error: 'Twilio' is not defined. but it's actually working and returning the Worker object. is there way to ignore or to say Vue js that I'm expecting Twilio?
Found a fix, you have to tell eslint that you'll have this as global, there are two ways to go:
add this before your variable call:
/* global Twilio */
or edit your eslint config:
'globals': {
'Twilio': 'readable'
},

What's causing Express not to pass my variables into the EJS template?

Express isn't passing my variable into the EJS template.
I've read this, this, this, this, this, and this. The most promising one is this... no dice.
I didn't find something that worked from these.
I've tried removing spaces from <%- loggedIn %> to no spaces <%-loggedIn%>, making the object in Express simpleres.render('test', {loggedIn: "Simple"}). I've triedapp.set("view options", { delimiter: "?" });` like I saw in the EJS/Express wiki, no dice.
// /backend/router.js
const app = express();
app.set("view engine", "ejs");
app.set("view options", { delimiter: "?" });
app.use("/", (req, res) => {
res.render("test", { loggedIn: "Test" });
});
// /views/test.ejs
<!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">
<title> </title>
</head>
<body>
User logged in: <%- loggedIn %>
</body>
</html>
I expected "User logged in: Test" to show when I went to localhost:8035. Instead I got ReferenceError, loggedIn not defined.
So I did know that when an Express server runs, it caches the routes file. New changes to the routes file in the editor doesn't reflect until restart. I knew this, but when I restarted before, I must've passed in an incorrect variable when I restarted the server. I restarted the server again and the error's no longer there.
But now it just shows User logged in: <%= loggedIn %>...

How to use Block inheritance in EJS templates

base.ejs:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>My Diary</title>
<link rel="stylesheet" href="stylesheets/bootstrap.min.css">
<script src="javascripts/jquery.js" ></script>
<script src="javascripts/bootstrap.min.js"></script>
</head>
<body>
<script type="text/javascript">
$(document).ready(function(){
});
</script>
</body>
index.ejs:
<div class="container">
<!-- Button trigger modal -->
<h1>Welcome to Your Diary</h1>
<div>
<span class="label label-default">What would you like to do? </span>
<span class="label label-primary">Here are your Categories:</span>
</div>
</div>
I want block inheritance
EJS does not specifically support blocks, but layouts can be implemented by including headers and footers, like so:
<%- include('header') -%>
<h1>
Title
</h1>
<p>
My page
</p>
<%- include('footer') -%>
https://github.com/mde/ejs#layouts
You could split base.ejs into two files, header and footer, like this:
header.ejs
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>My Diary</title>
<link rel="stylesheet" href="stylesheets/bootstrap.min.css">
<script src="javascripts/jquery.js" ></script>
<script src="javascripts/bootstrap.min.js"></script>
</head>
<body>
footer.ejs
<script type="text/javascript">
$(document).ready(function(){
});
</script>
</body>
</html>
Someone has made EJS with block inheritance capability (https://github.com/mafintosh/pejs)
Straight from the documentation (Retrieved on January, 1st, 2018):
Using blocks it's easy to implement template inheritance. Just declare
a base.html with some anchored blocks:
<body>
Hello i am base
<%{{ content }}%>
</body>
Then a child.html that renders base.html
<%{ './base.html' }%>
<%{ content %>
i am inserted in base
<%} %>
To render the example just render child.html
pejs.render('./child.html', function(err, result) {
console.log(result);
});
Looks pretty good. I'm going to try this on my own project.
You can use ejs-locals or ejs-mate engine for ejs
Sorry for being late. I am in the same situation. What you can do is to pass the content you want to render in the properties of the object. Like this:
<%- include('/partials/',{
title: 'my title',
tags: [
'<h1>Hi, my name is this</h1>'
]
});
%>
EJS does not support blocks, but this is the solution I have implementate. Hope it helps.

on layout:false losing client_side_validation properties

I am rendering partial on click using jquery. Here is the code for it
$('.actCell').click(function (){
alert('Load was performed.');
$.get('/policies/new', function(data) {
$('.policyAddForm').html(data);
});
});
Here is the controller code
def new
#policy = Policy.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #policy }
end
end
This is my application.html
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Passport</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<%= stylesheet_link_tag "application", :media => "all" %>
</head>
<body>
<div class="header">
<div class="container">
<img src="/assets/ph_logo.png">
<div class="user"><%=current_user.email%> <div class="userDrop"></div></div>
<div class="userDropMenu">
<div class="userActRow">change password</div>
<div class="userActRow">sign out</div>
</div>
</div>
</div>
<div class="nav">
<div class="container">
<%= yield %>
</div>
</div>
<%= javascript_include_tag "application" %>
<%= yield :javascript %>
</body>
</html>
With above code the problem is my layout get messed up. Div I updated with partial form shows header so it is layout in a layout but my client_validation_gem properties work. as soon as I say layout false my layout issue get fixed but I lose the client_side_validation gem properties. I dont know what is the issue and I am really frustrated. Any help or direction will be very helpful. Thanks,
Looks like you're not loading the rails.validations and rails.validations.custom js files if you use layout: false. You may have to include them in the partial (something like this).
= javascript_include_tag 'rails.validations'
Edit
Just saw that you're adding the form dynamically. You'll also need to trigger client-side validations like this after adding the form:
$('form[data-validate]').validate();
Finally I figured out. I have to remove rails.validations.js file because it was outdated. And add '$('form[data-validate]').validate();' to js file as #David suggested. Thanks for help

express js - ejs with layout template

In my express app,
I've changed the view engine to ejs.
Does anyone know if it is still possible to take advantage of view templates?
Actually after Express 3.X is not support layout.ejs, if you want to use the layout, following steps should be done by yourself:
add dependency "express-partials": "*" in you package.json file
"dependencies": {
"express": "3.1.0",
"ejs": "*",
"express-partials": "*"
}
execute npm install to install the latest version of express-partials
require express-partials in your app.js
var partials = require('express-partials');
add code app.use(partials()); under the app.set('view engine', 'ejs'); in app.js file
after that, you can design you layout.ejs and add <%- body%> block in your layout.ejs file, and that's enough and working well.
You can do it with this module...
https://github.com/aseemk/express-blocks
layout.ejs
<html>
<body>
<% include nav %>
<h1><%= title %></h1>
<%- body %>
</body>
</html>
login.ejs
<% layout('layout') -%>
<form>...</form>
nav.ejs
<nav>
<% if ( session.logged_in ) { %>
account
logout
<% } else { %>
signup
login
<% } %>
home
</nav>
I was using express-partials, but I found express-blocks to be better for ejs and express 3.x. using partials was a pain to have to pass data in everytime. With <% include whatever %> the data is already accessible.
In your routes file, you can render like this:
exports.login.get = function(req, res){
res.locals.session = req.session;
res.render('login', { title: 'Login to your account' });
};
Express.js leaves that up to the template engine if I remember correctly. So if ejs doesn't support layouts then you are out of luck.
Install ejs-blocks package npm install ejs-blocks
In your app.js file import the package const engine = require('ejs-blocks');
and configure view engine
//settings
app.set('views', path.join(__dirname, 'views'));
app.engine('ejs', engine);
app.set('view engine', 'ejs');
In express by default the name of the file is layout.ejs So create a file called layout.ejs in your views folder with the next content:
views/layout.ejs
<html>
<head>
<title><%= title %></title>
</head>
<body>
<%- body %>
</body>
<%- blocks.js %>
</html>
<%= title %> value is obtained when the file is called from route
router.get("/", (req, res) => {
res.render("index", { title: "Hello world!" });
});
Each of your views must import the layout.ejs file in the first line, for example
views/index.ejs
<% layout('layout') -%>
<h1>Article title</h1>
<p>Content</p>
...
<% block('js', `<script>
...
</script>`) -%>
You can use block for insert code from the view to the main layout.