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
Related
I keep getting the error in the title every time I attempt to host the server with nodemon.
Here is the code in the javascript file:
const express = require('express')
const path = require('path')
const app = express() // initialising express and saving as app
app.set('view engine', 'ejs')
app.set('views', path.join(__dirname, '/static/views')) // setting views directory to the views folder
app.use(express.static(path.join(__dirname, 'static')))
// redering home page
app.get('/', (req, res) => {
res.render('home.ejs')
})
// listening for requests on localhost 3000
app.listen(3000, () => {
console.log('Server is live!')
})
The code which I have shared above is in the index.js file. The home.ejs file has the following script tag:
<script type="text/javascript" src="/public/static/timer.js" defer></script>
The timer.js file is empty
app.use(express.static(path.join(__dirname, 'static')))
This line of code adds 'static' to the end of the directory where the index.js file is stored and makes the resulting directory static. It does not preserve the existing directory structure. So the script statement should be something like:
<script type="text/javascript" src="timer.js" defer></script>
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.
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)
This is not a question about express.static()
I have a application where I need to serve multiple pages which have same js and css dependencies. Hence, writing css and js includes using <script> or <link> tags on every single page is bad practice.
I am looking for a look alike php include way to do it. As php would process all php code and send compiled html, I think same could be done with js on node server.
So a server would do kinda like below:
get html from a resources.html
push above html to index.html
send index.html
Or perhaps there could be other way around. Any idea?
You can use layouts with your chosen template engine and each view can extend that layout. For example, if you're using Jade as your template engine.
index.js
var express = require("express");
var app = express();
var port = process.env.PORT || 7080;
app.set('view engine', 'jade');
app.get('/', function (req, res) {
res.render('home');
});
app.listen(3000);
views/layout.jade
doctype html
html
head
script(src='/javascripts/home.js')
link(rel='stylesheet', href='/stylesheets/style.css')
block title
title= "My Website"
body
.container
block content
views/home.jade
extends ./layout.jade
block content
h1 Hello World!
The home.jade view extends the layout and overrides the content block. Visiting http://localhost:3000/ returns the following:
<!DOCTYPE html>
<html>
<head>
<script src="/javascripts/home.js"></script>
<link rel="stylesheet" href="/stylesheets/style.css">
<title>My Website</title>
</head>
<body>
<div class="container"><h1>Hello World!</h1></div>
</body>
</html>
Make a public folder in your root directory
then in main app.js/server.js
add the following line :-
`var express = require('express'),
bodyParser = require('body-parser'),
userRoutes = require('./routes/user'),
mongoose = require('mongoose');
var app = express();
mongoose.connect('mongodb://localhost/meanDemo');
app.use( bodyParser.json() ); // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));
app.use(express.static('public'));
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');
app.use('/', userRoutes);
app.get('/',function(req, res){
res.render('userlist');
});
app.listen(3000);
console.log("sever started at 3000");
`
Then in views use /*filename to / will be your public directory
I have a working Node.js site, using Express.js, Handlebars.js and Consolidate.js. I want to use partials for common parts of my templates, but can't work out how to make them work for pages at different URLs.
My /views/ directory contains this:
_footer.html
_header.html
article.html
index.html
The relevant parts of my Node app looks something like:
var express = require('express'),
consolidate = require('consolidate'),
handlebars = require('handlebars'),
path = require('path');
var app = express();
app.engine('html', consolidate.handlebars);
app.set('view engine', 'html');
app.set('views', path.join(__dirname, '/views'));
var partials = {header: '_header', footer: '_footer'};
app.get('/', function(req, res) {
res.render('index', {partials: partials});
};
app.get(/^\/([\w-]+)\/$/, function(req, res) {
res.render('article', {partials: partials});
};
And in my index.html and article.html Handlebars templates I have something like:
{{> header}}
<!-- page content here -->
{{> footer }}
I should be able to access both / (when index.html is rendered) and /foo/ (when article.html is rendered). But it only works for whichever I try to access first after starting the Node server. When I then navigate to the other path, I get errors like:
Error: ENOENT, no such file or directory '/Users/phil/Projects/projectname/views/<!DOCTYPE html>...
with the rest of the _header.html partial following.
I assume I need to somehow set the path to my partials to be absolute somehow, but I can't see how to do that.
For consolidate check that : https://github.com/tj/consolidate.js/issues/18
I would recommend to switch to something a bit more specific like that https://github.com/donpark/hbs it will be simpler.
I had the same exact issue. It seems that consolidate is reusing the "partials" object that you pass, replacing the values with the file content (yuck!).
A workaround is to create a new "partials" object every time. If you don't want to rewrite the whole object every time, you can use a function returning the object literal.
In your case something like the following should work:
var express = require('express'),
consolidate = require('consolidate'),
handlebars = require('handlebars'),
path = require('path');
var app = express();
app.engine('html', consolidate.handlebars);
app.set('view engine', 'html');
app.set('views', path.join(__dirname, '/views'));
var partials = function() {
return {header: '_header', footer: '_footer'};
}
app.get('/', function(req, res) {
res.render('index', {partials: partials()});
};
app.get(/^\/([\w-]+)\/$/, function(req, res) {
res.render('article', {partials: partials()});
};
Not really elegant, but I don't think there is really a way to keep it simpler.