Very new to MEAN Stack and I'm using Brackets to edit .ejs views for a simple form app using Express tutorial. I'm trying load a static image and it just won't load. I'm getting GET /public/ggcbear.jpg 404 from app.js (terminal). I also created a image.ejs views to handle the load...but thats not working. My .jpg is listed in the folder: public. What syntax is wrong in my code/.ejs files?
Part of my app.js
var http = require("http");
var path = require("path");
var express = require("express");
var logger = require("morgan");
var bodyParser = require("body-parser");
// Make an express app
var app = express();
app.set("views", path.resolve(__dirname, "views"));
app.set("view engine", "ejs");
//adding static functionality for images
app.use(express.static('public'));
// Renders the "image" page (at views/index.ejs) when GETing the URL
app.get("/image", function(request, response) {
response.render("image");
});
//etc...
my header.ejs
<!-- This header will appear at the top of every page -->
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<title>Express Guestbook</title>
<!-- Loads Twitter's Bootstrap CSS from the Bootstrap CDN -->
<!-- http://getbootstrap.com/ -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body class ="container">
<!-- my image tag -->
<div>
<img src="/public/ggcbear.jpg">
</div>
<h1>
Express Guestbook
<a href="/new-entry" class="btn btn-primary pull-right">
Write in the guestbook
</a>
</h1>
</body>
</html>
my image.ejs
<% include header %>
<div>
<h3><img src="/ggcbear.jpg", alt="Testing Image")</h3>
</div>
<% include footer %>
Using the following static middleware:
app.use(express.static('public'));
and the following folder structure:
.
├── app.js
├── public
│ └── images
│ └── ggcbear.jpg
└── view
├── header.ejs
└── image.ejs
your ggcbear.jpg will serve from /images/ggcbear.jpg:
<img src="/images/ggcbear.jpg">
Related
I'm working on NodeJs application.
I created route for admin page also made a layout for it.
app.js
app.engine('.hbs', expressHsb({defaultLayout: 'default', extname: '.hbs'}));
app.set('view engine', '.hbs');
/* configure express */
app.use(express.json());
app.use(express.urlencoded({extended: true}));
app.use(express.static(path.join(__dirname, '/public')));
/* routes */
const adminRoutes = require('./routes/adminRoutes');
app.use('/admin', adminRoutes);
app.use('/posts', adminRoutes);
My app folder structure looks like this:
Also the admin page has a part for creating posts which is in admin/posts/create route.
adminControllers.js
module.exports = {
index: (req, res) => {
res.render('admin/index');
},
createPosts: (req, res) => {
res.render('admin/posts/create');
}
};
adminRoutes.js
router.route('/')
.get(adminController.index);
router.route('/posts')
.get(adminController.getPosts)
.post(adminController.submitPosts);
router.route('/posts/create')
.get(adminController.createPosts);
When I start my app and I go to admin page everything works fine but when I enter create post part that has form my stylesheets and js files can't be reached.
On page there is html structure but no functionalities or style and when I view source code in browser and for example click on link like
<link href="css/sb-admin-2.min.css" rel="stylesheet">
I get following error:
Cannot GET /admin/posts/css/sb-admin-2.min.css
Like it's searching css folder in post folder and not in public.
Admin layout looks like this:
{{> admin/admin-header }}
<body id="page-top">
<!-- Page Wrapper -->
<div id="wrapper">
<!-- Sidebar -->
{{> admin/admin-sidebar}}
<!-- End of Sidebar -->
<!-- Content Wrapper -->
<div id="content-wrapper" class="d-flex flex-column">
<!-- Main Content -->
<div id="content">
<!-- Topbar -->
{{> admin/admin-topNav }}
<!-- End of Topbar -->
<!-- Begin Page Content -->
<div class="container-fluid">
{{{body}}}
</div>
<!-- /.container-fluid -->
</div>
<!-- End of Main Content -->
<!-- Footer -->
{{> admin/admin-footer}}
<!-- End of Footer -->
</div>
<!-- End of Content Wrapper -->
</div>
<!-- End of Page Wrapper -->
Everything works fine for admin page but if I go to link on admin page
<a class="collapse-item" href="/admin/posts/create">Create new Post</a>
It's just not loading as already mentioned stylesheets or js files, like that part of code doesn't belong as body to admin layout.
I am not sure why is this happening any advice highly appreciated.
css/sb-admin-2.min.css is a relative link. Change it to /css/sb-admin-2.min.css.
Technically it is still a relative link, since it doesn't include protocol or host, but the important part in this case is that the path is absolute
I'm working in a new web portal. So far using the express and node.js i have a server and some ejs files.
The body structure of my site is like this:
- node modules
- public
--javascript
---myScript.js
-views
--pages
---index.ejs
---about.ejs
--partials
---footer.ejs
---head.ejs
---header.ejs
package.json
server.js
server.js
var express = require('express');
var app = express();
app.set('view engine', 'ejs'); // set the view engine to ejs
app.get('/', function(req, res) {res.render('pages/index');}); // index page
app.get('/about', function(req, res) { res.render('pages/about');}); // about page
app.listen(8080);
console.log('Portal is listening to port 8080 ');
and the index.ejs
<html lang="en">
<head>
<% include ../partials/head %>
</head>
<body class="container">
<header>
<% include ../partials/header %>
</header>
<main>
<div class="jumbotron">
<h1>MyPortal</h1>
<button>Press</button>
<% var test = 101; %>
</div>
</main>
<footer>
<% include ../partials/footer %>
</footer>
</body>
</html>
In the partials i want to call and use an external .js file /public/javascript/myScript.js so i can use variable from it in my ejs page or send a variable.
my js file have a simple function (just to see if it's working) that print in console if the button (in index.ejs) is pressed.
myScript.js
$(function() {
$("button").on("click", function () {
console.log("button pressed");
});
});
I'm trying to call the external js in head.ejs (or in index.ejs)...
<!-- views/partials/head.ejs -->
<meta charset="UTF-8">
<title>MyPortal</title>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<style>body { padding-top:50px; } </style>
<script type="text/javascript" src="/pubic/javascript/myScript.js"></script>
but i'm getting this error (in console)
Loading failed for the <script> with source “http://localhost:8080/pubic/javascript/myScript.js”.
Any idea why this happens and how to solve it?
Since you are trying to load client-side JavaScript, the fact you are using EJS is irrelevent. A standard HTML script element is all you need in the template, and you have that.
You do, however, need to provide a URL (with the src attribute) that the web browser can use to fetch the script … and your script has no URL.
You are getting the message Loading failed for the with source “http://localhost:8080/pubic/javascript/myScript.js”. because it is a 404 Error.
You should use the static module to provide the JS file with a URL.
app.use("/public", express.static('public'))
Add this to your server.js file,
app.use(express.static(__dirname + "/public");
And to link the js file with your ejs file,
I want to navigate to next page using link but i'm facing 404 error
I'd changed my template from jade to ejs
<html>
<body>
<div>
<ul style="color:white; float: right;" class="nav navbar-nav">
<li>Login </li>
<li>Sign Up </li>
</ul>
</div>
</body>
</html>
#Asad, in order for you to go to /login, you must have this route declared in your server side. Something like:
app.get('/login', (req, res) => {
res.render('login');
});
Otherwise, you will always have 404.
Using the following dependencies NPM:
"dependencies": {
"body-parser": "^1.19.0",
"ejs": "^3.0.1",
"express": "^4.17.1",
"mongoose": "^4.13.20"
In app.js file:
const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const app = express();
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({extended: true}));
app.use(express.static("public"));
In Ejs File:
<a class="btn btn-dark btn-sm" href="/someFile" >Link to some EJS File</a>
your file structure:
project
node modules
public
views
index.ejs
someFile.ejs
By setting the view engine to ejs in the app.js file and setting the static file folder in the same app.js you may be able to call out to other ejs files in the same directory utilizing "/" for href. Hope this helps. This is my first answer on Stackoverflow so take it easy on me.
"Image for Navigating Different Web Pages"
As illustrated in the image above, the best way to navigate different web pages using ejs template is to ensure you create a folder called "partials" in your project's "views folder directory" where you have your other ejs files.
1) Then in that "partials folder" create 2 separate ejs files called header.ejs & footer.ejs.
2) Then go to your home.ejs or index.ejs file depending on how you have named your starting ejs file, and then cut ("All contents including the css and probably the bootstrap links in the boiler plate down to the opening body tag <body> and paste in the header.ejs file in the partials folder").
3) Also cut ("All contents from the closing body tag </body> of the "home or index.ejs " file to the footer.ejs file in the partials folder"). Then instead of repeating the header and footer sections for the subsequent pages i.e about.ejs or contact.ejs just link them to the header.ejs and footer.ejs files in the partialss folder as below:
//Sample page of the about.ejs file
Visual Illustration:
<%- include("partials/header"); -%>
<h1> About Page </h1>
<p> This is an about page </p>
<%- include("partials/footer"); -%>
//Do same for other pages.
Finally, following the image above, link the navigation to the different pages at the anchor tags in the header.ejs file which is located in the partials folder using:
"/" ----- To Home Page.
"/about" ------ To About Page.
"/contact" ------ To Cntact Page.
I hope this helps. Please let me know your views.
Something similar to this should be on your login.ejs page. Also, pay attention to spellings and all.
...
In server file
app.get('/login', (req, res) => {
res.render('login');
});
I faced the same issue and that's how I got it fixed.
And the login file should actually be created.
App js.
const express = require("express");
const ejs = require("ejs");
const startingContent = "Home Page";
const aboutContent ="About Us Page";
const app = express();
app.set('view engine', 'ejs');
app.use(express.urlencoded({extended: true}));
No Need for body parser, express handles that already, by using : app.use(express.urlencoded({extended: true})); .
app.use(express.json());
app.use(express.static("public"));
app.get("/", (req, res)=>{
res.render("home", {homeStart: startingContent});
});
app.get("/about", (req, res)=>{
res.render("about", {aboutStartingText: aboutContent});
});
app.listen(3000, ()=> {
console.log("Server started on port 3000");
});
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>My Site</title>
<meta charset="utf-8">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="/css/styles.css">
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<p class="navbar-brand">My Site</p>
</div>
<ul class="nav navbar-nav navbar-right">
<!-- 6 -->
<li id="home">HOME</li>
<li id="about">ABOUT US</li>
</ul>
</div>
</nav>
<body>
<div class="container">
Header.ejs
Best practice is to have your header and footer in a folder partials
Example :
views
partials
header.ejs
footer.ejs
home.ejs
about.ejs
Then you render in your ejs file.
<%- include("partials/header") -%>
<h1>Home</h1>
<p><%= homeStart %></p>
<%- include("partials/footer") -%>
For example:
Routes in *.js:
app.get("/", function (req, res) {
res.render("home", { contentHome: homeStartingContent});
});
app.get("/about", function (req, res) {
res.render("about", { contentAboutpage: aboutContent });
});
app.get("/contact", function (req, res) {
res.render("contact", { contentContactpage: contactContent });
});
Links in HTML:
<li id="home">HOME</li>
<li id="about">ABOUT US</li>
<li id="contact">CONTACT US</li>
I have a problem loading external files into my index.html. My stylesheet as well as my JS files do not show up at all (Error 404 - Not Found). My directory structure is as follows.
My index.html is:
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<title>Orders and Customers</title>
<link rel="stylesheet" type="text/css" href="./assets/css/stylesheet.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular-route.min.js"></script>
<script src="./../app/app.js" type="text/javascript"></script>
<script src="./../app/controllers/customer/CustomerController.js"></script>
<script src="./../app/controllers/order/OrderController.js"></script>
<script src="./../app/services/customer/CustomerService.js"></script>
<script src="./../app/services/order/OrderService.js"></script>
</head>
<body>
<div ng-view></div>
</body>
</html>
This is what Chrome shows:
My server.js is:
var express = require('express');
var path = require('path');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.json());
require('./server/config/mongoose.js');
require('./server/config/routes.js')(app);
app.use(express.static(path.join(__dirname, './views')));
app.listen(8000, function() {
console.log('Listening on Port 8000');
})
Any help is greatly appreciated!
Try this
in server.js
var router = express.Router();
router.use(express.static(path.resolve(__dirname, "../app")));
in index.html
<script src="/app.js" type="text/javascript"></script>
<script src="/controllers/customer/CustomerController.js"></script>
<script src="/controllers/order/OrderController.js"></script>
<script src="/services/customer/CustomerService.js"></script>
<script src="/services/order/OrderService.js"></script>
Router is middle-ware for capture * path.
For example, /service/* matches all requests under service path.
so I changed your code as to handle all resources under "/app" folder. (eg: /app/app.js, etc)
path.resolve changes path from relative to absolute.
it means that you can add another current working directory.
path.resolve(__dirname, "../app") add "/app" from current working directory (views). it parsed from "views/../app" to "/app"
(Reference) Path.resolve
The relative paths
<script src="./../app/app.js" type="text/javascript"></script>
etc, are pointing to the wrong directory.
Use the Network tab in your browser developer tools, to check what exact requests are going out.
If the whole app directory is public (Which, in my opinion, should not be the case), "./../" will refer to the views directory.
Single . refers to the current directory, which in this case is, the one containing your index.html. Double .. refers to the directory above it, which here is views.
Rather than
<script src="./../app/app.js" type="text/javascript"></script>
Try using the full path:
<script src="/app/app.js" type="text/javascript"></script>
<script src="/app/controllers/order/OrderController.js"></script>
Try this
app.use(express.static(path.join(__dirname, 'views')));
and just use
<link rel="stylesheet" type="text/css" href="assets/css/stylesheet.css">
Thanks to SeongHyeon, I was able to figure out the solution to my problem. I really appreciate your guys' help. I'd like to elaborate more on this just for my own reference.
When declaring your static path in express, you don't need to reference anything relative to the file that you're trying to import from. Instead, you simply reference the file from the static path that you've declared.
When I render my .ejs file the href and the src attributes are not referencing my local files. I am using node.js and express.
Here is the relevant part of the .ejs template.
<head>
<title></title>
<link rel='stylesheet' href='../public/stylesheets/styles.css' />
<script src="../us-map-1.0.1/lib/raphael.js"></script>
<!-- <script src="scale.raphael.js"></script> -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.js"></script>
<script src="../us-map-1.0.1/color.jquery.js"></script>
<script src="../us-map-1.0.1/jquery.usmap.js"></script>
<script>
</head>
This is router that renders the template
router.get('/submit', function(req, res, next) {...});
And this is what a typical query looks like
http://localhost:3000/submit?leftHashtag=dog&rightHashtag=cat
Any help on why this is happening would be greatly appreciated.
The problem was that I wasn't defining my static content serving.
To fix this I added an app.use statement to my app.js file
app.use('/submit', express.static(__dirname + '/public'));
So now any routes that begin with /submit will use this directory local to the app
__dirname/public
With __dirname being the current directory the app.js file is located in
If you would like to know more this blog goes into more detail about what is happening
http://blog.modulus.io/nodejs-and-express-static-content