using common layout for all the pages in pug - javascript

I am trying out pug with express
views/layout.pug
doctype html
html
head
title= title
link(rel="shortcut icon", href="favicon.ico", type="image/x-icon")
link(rel='stylesheet', href='/assets/application.css')
link(rel='stylesheet', href="assets/libs/bootstrap/dist/css/bootstrap.min.css")
body
script(src="assets/libs/jquery/dist/jquery.min.js")
script(src='assets/libs/bootstrap/dist/js/bootstrap.min.js')
script(src="assets/application.js")
block content
This is the router for User page.
routes/user.js
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/', function(req, res, next) {
res.render('user/index');
});
module.exports = router;
I have my view for user/index page. I extends the layout from the views. User index page using the layout. layout.pug is present in views folder.
If I add a layout.pug inside views/user it works. But how to use the views/layout.pug
/views/user/index.pug
extends layout
block content
h1
| User index
i get the following error. it is looking for layout in view/user folder. How to make it to use view/layout.pug.
Error: ENOENT: no such file or directory, open 'C:\my_projects\myexpressapp\views\user\layout.pug'
at C:\my_projects\myexpressapp\views\user\index.pug line 1
at Error (native)
at Object.fs.openSync (fs.js:640:18)
at Object.fs.readFileSync (fs.js:508:33)
at Function.read (C:\my_projects\myexpressapp\node_modules\pug-load\index.js:69:13)
at Object.read (C:\my_projects\myexpressapp\node_modules\pug\lib\index.js:147:25)
at C:\my_projects\myexpressapp\node_modules\pug-load\index.js:24:25
at walkAST (C:\my_projects\myexpressapp\node_modules\pug-walk\index.js:23:18)
at C:\my_projects\myexpressapp\node_modules\pug-walk\index.js:104:20
at Array.reduce (native)
at walkAndMergeNodes (C:\my_projects\myexpressapp\node_modules\pug-walk\index.js:103:18)

In your app.js file, check whether you have defined the views properly.
View engine should be set to pug and views folder should be set properly as described below in app.js
app.set('view engine', 'pug');
app.set('views', path.join(__dirname, 'views'));

You have to set the baseDirectory variable.
I'm not familiar with Express, I found the answer How do you set jade basedir option in an express app? (the "basedir" option is required to use "extends" with "absolute" paths)

Related

Returning a page through HTTP with express

I have a folder called "Public" which contains an index.html file a long with some JavaScript and library files. When someone tries to access the products path (mydomain.com/products) I want to display that index.html file, but the client also needs to receive all the JavaScript and libraries. Here is the code for how I initially handle the HTTP request.
const express = require('express')
const app = express()
const bodyParse = require('body-parser')
const productRoutes = require('./api/routes/products')
const orderRoutes = require('./api/routes/orders')
app.use(bodyParse.urlencoded({extended: false}))
app.use(bodyParse.json())
// Routes which handle requests
app.use('/products', productRoutes)
app.use('/orders', orderRoutes)
In the products.js file, I continue the routing like this:
const express = require('express')
const router = express.Router()
router.get('/', (req, res, next) => {
/*res.status(200).json({
message: 'Handling GET requests to /products'
})*/
res.status(200).render("../../public")
})
The code I've commented out works perfectly fine, but I'm struggling to respond with the "public" folder page. I can't remember everything I've tried, but using .render or .sendFile on the "public" directory has not worked for me.
When I try to access the /products route, I'm hit with an empty error message. As it fails to return anything in the /products route, in continues down the file to an error handler. The error message is empty.
Any ideas on how to display the page with all the folder contents would be great!
Try: app.use('/products', express.static('public'))
This makes your "public" directory viewable from the /products route.
express.static() docs
You must config path for express static by :
//app.js | server.js
app.use(express.static(__dirname + '/public'));
Then, in example you have a file as : /public/you.html
In your app, you can use that file as path /you.html
And the same with all files type *.js, *.css,...
Fix error cannot view error
Run cmd npm install ejs
Att to app.js:
app.set('view engine', 'ejs');
After that, you create 1 file error.ejs at folder views :
//error.ejs
<%=error%>
Goodluck

$ Undefined on (Node+Express+Pug+JQuery)

A Newbie question for sure, but I'd appreciate any help, as I'm completely stuck (ie, I tried everything I could find without success).
When I try to use Jquery, i get "ReferenceError: $ is not defined".
My project structure is:
bin/www
public
javascripts
stylesheets
routes
index.js
views
layout.pug
...
app.js
layout.pug, where I try to load CDN jquery is:
doctype html
html(lang='en')
head
meta(charset='utf-8')
title= title
//- bootstrap CSS
link(rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css'
integrity='sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u' crossorigin='anonymous')
link(rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css')
//- my Styling CSS
link(rel='stylesheet', href='/stylesheets/style.css')
body
block content
script(src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js")
script(src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous")
script(src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js'
integrity='sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa' crossorigin='anonymous')
script(src='/javascripts/jquery-3.3.1.js')
script(src='routes/index.js')
My index.js file is the following:
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function (req, res, next) {
res.render('index', { title: 'Express' });
});
$(function () {
alert('JavaScript Loaded!');
});
module.exports = router;
Finally, in my app.js file these are some relevant lines:
const indexRouter = require('./routes/index');
const app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
// Set Static Paths
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
Can anybody help me?
I think that you don't know server-side-rendering vs client-side-rendering.
Expressjs is server-side-rendering. so you don't call jQuery in index.js
If you call jQuery, you do this. var $ = require('jQuery');
reference: https://www.npmjs.com/package/jQuery#nodejs

Error: Module "html" does not provide a view engine (Express)

I'm trying to set up a simple routing app but I keep running int the error when rendering a page.
Error: Module "html" does not provide a view engine.
What is odd is I've specified the view engine in my app.js file but I'm still getting the error
// app.js
var express = require('express');
var app = express();
var router = express.Router();
// Need to import the route file
var chef = require('./chef');
app.use('/chef', chef);
// Set directory to contain the templates ('views')
app.set('views', __dirname + '/views');
// Set view engine to use
app.set('view engine', 'html');
app.use(function(err, req, res, next) {
console.error(err.stack);
res.status(500).send('Something broke!');
});
// chef.js
var express = require('express');
var routes = express.Router();
routes.get('/', (req, res) => {
//res.send("I'm here!")
res.render('chef');
});
module.exports = routes;
// views/chef.html
Some HTML file here here ..
In the chef.js file when I just want to test if the route is working I uncomment res.send ... which sends "I'm here" to the DOM.
However whenever I try res.render to render the chef.html page I get the error above. Which I find odd because I've set the view engine in app.js.
Suggestions on how to render my HTML file?
use res.sendFile('/fileName.html'); instead of res.render()
for sending file , we used res.sendFile(fullPath) and if you are using other than HTML language then you should have to use res.render().
res.render() for template like ejs, pug etc.

How can I have my index.htm file include other html files

using node.
Here is how I serve one from my server:
app.get('/', function(req, res) {
res.sendfile('./views/index.html');
});
With in this index.html file I have two files I need served:
head.htm and body.htm.
In PHP I would just use includes. How is this done in Node?
There's many solutions to the situation here... it comes down to personal preference on which tool you gravitate towards.
One such tool that I have used is EJS. You can read all about it here:
https://code.google.com/archive/p/embeddedjavascript/wikis/Templates.wiki
Edit: An example of such would be having a header and footer template, with an index.ejs page that includes them. (Although you can use include these files at any point in the index page that gets rendered).
Index.ejs (ejs is just the extension used, it's the same as html with rendering tags inside of it):
<% include templates/header %>
<h1> Index page!</h1>
<% include templates/footer %>
Header.ejs:
<html>
<head>
</head>
<body>
Footer.ejs:
</body>
</html>
Inside routes configuration:
app.get("/", function(req, res){
res.render("index");
}
There's obviously configuration requirements that you will need to do, I'm also assuming you're using express, which EJS works pretty easily with.
Pick a template library, any template library. I've had success with nunjucks.
Then you can do something like:
var nunjucks = require("nunjunks");
var app = express();
nunjucks.configure('views', {
autoescape: true,
express: app
});
app.get('/', function(req, res) {
res.render('index.html');
});
and in index.html:
{% include "item.html" %}
It would help if you mentioned the templating engine you are using. By default, it should be Pug(or Jade) (if you used the express generator I think).
For Jade:
app.js:
var express = require('express');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
// define routes
app.get('/', function(req, res) {
res.render('index.html');
});
Now, by default the views folder will be used to serve files. A good practice is to create a master layout that defines the general structure of your HTML files, and then add the specific contents in the extended files.
master.pug:
doctype html
html
head
title
block title // title block
link(rel='stylesheet', href='/stylesheets/default.css') //some default styles
block styles // block for more styles
body
include header.pug //include header file
block content // block to insert contents
script(type='text/javascript',src='/javascripts/faculty-index.js') // default scripts
block scripts // block to insert scripts
include footer.pug // include footer file
Block defines a space where you can enter your content once you extend the file. Include basically just includes the code from the file in that space. Now you're index.pug can be something like this
index.pug
extends master.pug // extend the base template
block title
| Index Page // adds the content in the title block
block styles
link(rel='stylesheet', href='/stylesheets/index.css') // specific styles for index
block content
h1 This is the index // adds the index content which goes in the body tag where content is defined
Here the index file uses everything from the master file, and adds its own content in title, body and styles.
Look at the pug documentation for more
Similar behavior can be replicated with any templating engine. Another one I've used is Handlebars which I like more because its syntax feels more like writing html. But, you'll have to set it up first.

How to easily pass a variable with Node.js to the view

I'm trying to learn the basics of Node.js and I can't seem to be able to simply send a variable from app.js to index.html without using Jade or other template engine.
This is my app.js
var express = require("express");
var app = express();
app.get('/', function(req, res){
//I'd like to send this as a variable instead
res.send("some text");
});
app.listen(8080);
This is my index.html
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
//I want to alert my variable here please
alert(variableFromAppjs);
</script>
</head>
<body>
<p>Hello</p>
</body>
</html>
Is there a way to do it simply like that?
The reason you can't just "send" the variable from your app.js to index.html is because they're two separate programs. index.html is run ONLY on the client machine through the browser, and app.js is run ONLY on the server.
In order for index.html to receive data from app.js, you'll need to to use XMLHttpRequest to make a request to your Node app.
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
You can then receive the data asynchronously and save it to whatever variable you want.
You will need to make sure you're using a server-side templating engine (express comes with jade support).
Use npm to install jade to your express app. and then tell express where the templates are, and, in the get route definition you must instruct express what view to use:
var express = require("express");
var app = express();
// Tell express where your templates are
app.set("views", __dirname + "/views");
// Tell express templates are jade files
app.set("view engine", "jade");
app.get("/", function(req, res) {
res.render("home", {
title: "Home Page",
body: "This is just a test..."
});
});
app.listen(8080);
when all this is setup create views/layout.jade and a views/home.jade
Home.jade will look like this:
extends layout
block content
h1= title
p A tag name followed by the equals (=) sign is like php echo
p= body
ul
li This is a hardcoded list
li With two elements
Layout.jade will look like this:
html
head
meta(charset="utf-8")
title= title
link(rel="stylesheet", href="/css/main.css")
meta(name="viewport", content="width=device-width")
body
block content
div.page-content.text-center
h1 Default content
p anything I put here will be overridden by the home.jade content block Which means that any jade view that doesn't provide a `block content` part will render this text instead.
If you create another route for example:
app.get("/default", function(req, res) {
res.render("test", {title: "Default route", body: "Whatever"});
});
an then its corresponding template views/test.jade
extends layout
p I'm not providing a `block content` so this text won't be rendered
blockquote(class="my-class", id="my-id") In jade, the very first word of a line is the tag to be used by the line, to provide attributes to a tag you use comma-separated HTML attributes in between parenthesis right next to the tag name.
And visit your route at http://localhost:8080/default You will see the default text be rendered.
I hope this is of help.

Categories