I am really new to the whole MEAN-stack and are trying to create an application on openshift but are unable to render a new page.
I just keep getting this error and can't solve it with anything I've googled.
My Error: Failed to lookup view "/register" in public directory
It works completely fine to render the index page with app.get('/', func()) in server.js and tried to to the exact same thing with app.get('/register). I used to have the same problem with '/' at first but solved it using app.use(express.static(__dirname + '/public'));
Both index.html and register.html are located in the public directory.
These are extracts of my code:
index.html
<body ng-app="">
<div class="container" ng-controller="LoginController" >
<h1>Logg in</h1>
<input class="form-control" placeholder="ID"/>
<input class="form-control" placeholder="Password"/>
<button class="btn">Logga in</button>
<button ng-click="open()" class="btn">Register User</button>
</div>
</body>
logincontroller
function LoginController($scope, $http) {
console.log("Hello from Login");
$scope.open = function () {
console.log('open i login.js');
$http.get('/register')
};
};
server.js
var express = require('express');
var fs = require('fs');
var mongojs = require('mongojs');
var jade = require('jade')
var app = express();
var cors = require('cors');
var bodyParser = require('body-parser');
app.use(express.static(__dirname + '/public'));
app.use(express.bodyParser());
app.get('/env',function(req, res){
res.json(process.env);
});
app.get('/', function (req, res) {
res.render('/index', {});
});
app.get('/register', function (req, res) {
res.render('/register');
});
app.set('view engine', 'jade');
There are a couple of issues.
1) Don't use a slash for the 'register' file. This is a file in the /public folder, not a folder or route.
app.get('/register', function (req, res) {
res.render('register');
});
2) You have set jade as your rendering engine. This means you will be serving .jade files. Your public folder should have index.jade. And it should look like this:
html
body(ng-app='')
.container(ng-controller='LoginController')
h1 Logg in
input.form-control(placeholder='ID')
input.form-control(placeholder='Password')
button.btn Logga in
button.btn(ng-click='open()') Register User
A couple of notes:
Jade is a HTML templating engine, it's relatively straight forward, see http://jade-lang.com/tutorial/.
There is express-generator which will give you an example app, it's an excellent starting point: http://expressjs.com/en/starter/generator.html
By the way, there is also an HTML-2-Jade converter, I find this helpful sometimes: http://html2jade.org/
Related
I am trying to pass a string from the frontend into the backend, but I have hit a roadblock. I am using Node, Express, Body Parser, EJS, and PostgreSQL. My basic file system is this:
– app
|– api
| |– thing.js
|
|– index.js
– views
|– pages
|– index.ejs
I have a form submission in index.ejs that passes data to the index.js file:
index.ejs
<form action="/creatething" method="post">
<h1>Make a thing</h1>
<p> What is your thing called?
<input name="wtitle" type="text">
</p>
<p> What is your name?
<input name="cuser" type="text">
</p>
<input type="submit" value="Submit">
</form>
The above code triggers /creatething, which is placed in index.js
index.js
const express = require ('express');
const thingRouter = require('./api/thing');
const bodyParser = require("body-parser");
const app = express();
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({extended: false}));
app.use('/thing', thingRouter);
app.get('/', function (req, res){
res.render('pages/index');
});
app.post('/creatething',(req,res)=>{
console.log('clicked '+ req.body);
});
module.exports= app;
With this I am able to create a message in the console that prints the user input from the form. However, I am trying to send this data to a database through code in thing.js:
thing.js
const {Router} = require('express');
const router = new Router();
router.get('/',(req,res)=> {
console.log(req.body);
// Placeholder for working code that stores thing in database :)
});
module.exports = router;
The problem here is that I don't know how to pass the req.body data from the index.js file to the thing.js method that inserts the data into the database. I could just add the database code into the index.js file, but I was trying to keep things more separated and learn about routing/mounting. What am I missing at this point?
You have to change a few things in your thing.js file. Only few lines of code is required instead of importing Router from express and add some extra routes.
Just copy below code and paste to your respective files.
thing.js
const get = (req, res) => {
console.log(req.body);
}
module.exports = get;
index.js
const express = require ('express');
const get = require('./api/things');
const bodyParser = require("body-parser");
const app = express();
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({extended: false}));
app.get('/', function (req, res){
res.render('pages/index');
});
app.post('/creatething', (req,res)=>{
get(req,res);
});
app.listen(4000, () => {
console.log('App is running on port: 4000');
});
module.exports= app;
Hope this helps you solve the issue.
I'm still fairly new to Express.js. I have a question about sending form data to an existing template. I have two routes which have template views associated with them. One page has a form on it and I want to take inputs from that form to populate the other template of the other route. I'm using Hanglebars for my template engine.
I've found a lot of helpful answers here (this one especially Cannot POST form node.js - express ), but none that quite answer my question.
I know how to post to create a new page with the form data. Like this:
router.post('/game', function(req, res) {
res.send(req.body.username);
});
But how do I get req.body.username accessible to a handlebars template? I've been reading various tutorials and it looks like I need to do something with next() in app.use('/game', game);. But I'm getting lost as to what exactly that is.
Here's a simplified version of my code.
My main server file:
var express = require('express');
var exphbs = require('express-handlebars');
var app = express();
var http = require('http').Server(app);
var path = require('path');
var io = require('socket.io')(http);
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var routes = require('./routes/index');
var game = require('./routes/game');
app.engine('handlebars', exphbs({defaultLayout: 'main'}));
app.set('view engine', 'handlebars');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/game', game);
// view engine setup
app.set('views', path.join(__dirname, 'views'));
http.listen(3000, function(){
console.log('listening on *:3000');
});
My route file "index.js":
var express = require('express');
var exphbs = require('express-handlebars');
var app = express();
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res) {
res.render('index', {
title: 'Pick a Player',
});
});
module.exports = router;
Here is the form on index.handlebars (just the form):
<form method="post" action="/game" novalidate name="pick-a-player" id="pickAPlayer" class="form-box">
<p>What is your name?</p>
<input type="text" name="username" placeholder="name">
<p>Please select a player</p>
<label>
<input type="radio" name="player" value="Jane" checked> Jane<br>
<input type="radio" name="player" value="Sue"> Sue<br>
<input type="radio" name="player" value="Anne"> Anne<br>
</label>
<input type="submit" value="Start the game" id="submitCharacterForm">
</form>
I know I need to use post to get the data through req.body. But I'm getting the template through .get(). How do get the two to communicate?
Here's the route for game.js
var express = require('express');
var exphbs = require('express-handlebars');
var app = express();
var router = express.Router();
/* GET Game page. */
router.get('/', function(req, res) {
res.render('game', {
title: 'Let's Play',
username: req.body.username,
player: req.body.player
});
});
module.exports = router;
When the value of player gets called on game.handlebars, it looks like this:
<p class="player-card">{{player}}</p>
If I'm understanding this correctly, the main form will have two values on the request body: username and player.
This form will make a POST request to /game according to your form block:
<form method="post" action="/game" ...>
You handle this POST request with the following route handler:
router.post('/game', function(req, res) {
res.send(req.body.username);
});
And you want to send the username and player values to your game template correct?
If I'm understanding this correctly, you can either res.redirect with data or simply render a different view with the data:
router.post('/game', (req, res) => {
const { username, player } = req.body
res.render('play-game', { username, player });
});
So I'm working on developing a Node/Express webapp for basic CRUD operations and I'm having a hard time implementing Handlebars within the project.
When I try to use handlebars none of my stylesheets from my .hbs (previously .html) pages are loading.
Here's the file tree:
Here is the error:
And here is an example of the script import statements from
index.hbs
<!-- Bootstrap -->
<link href="../vendors/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
And Finally here is the server.js file
var express = require('express'),
bodyParser = require('body-parser'),
path = require('path'),
mysql = require('mysql'),
dbconfig = require('./config/database'),
exphbs = require('express-handlebars');
var connection = mysql.createConnection(dbconfig.connection)
connection.query('USE ' + dbconfig.database);
var app = express();
//Body Parser Middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
//Set static path
//app.use(express.static(path.join(__dirname, 'public')));
//app.use(express.static(__dirname + '/public'));
//app.set('views', __dirname + '/views');
//app.use('/views', express.static(path.join(__dirname, '/views')));
app.engine('hbs', exphbs({defaultLayout: false}));
app.set('view engine', 'hbs');
app.set(express.static(__dirname + '/public'));
//app.use('/views/vendors', express.static(path.join(__dirname, '/views/vendors')));
//app.use(express.static(__dirname + '/public/vendors'));
app.get('/', function(req, res) {
res.render('index');
connection.query("SELECT * FROM Student", function(err, rows){
console.log(rows);
});
});
app.listen(80, function() {
console.log('we are live on 80');
});
I tried using various static paths from other things I found on SO but wasn't able to get any of them to work.
Any help would be greatly appreciated!!
Thanks!
Fixed my problem by adding the following line above my app.get('/'....
app.use("/vendors",express.static(__dirname + "/vendors"));
app.use("/build",express.static(__dirname + "/build"));
app.use("/images",express.static(__dirname + "/images"));
app.get('/', function(req, res) {
I think that can be possible that the problem is in the handlebars configuration, please look at a configuration like this:
app.engine('.hbs',exphbs({
defaultLayout:'layouts',
layoutsDir:path.join(app.get('views'),'layouts'),
partialsDir:path.join(app.get('views'),'partials'),
extname:'.hbs',
helpers: helpers
}));
app.set('view engine','hbs');
maybe in yours it would be:
app.engine('hbs', exphbs({defaultLayout: false, extname:'.hbs',}));
if you are usign app.set(express.static(__dirname + '/public'));
try to put in the public folder your styles for example the bootstrap folder, and then all you have to do is call it in this way:
<link href="/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
I write a simple program which is really unreadable. At first, I didn't know how to use template so I decide, in spite of that, to write html code inside my node.js code.
(solved)
Try something like this
I usually have a project structure like:
lib
node_modules
public (This is where the CSS and page JS goes)
routes
views (This is where you put your EJS templates)
app.js
In your package.json make sure you have included ejs
"ejs": "*"
In app.js (assuming you use express)
var express = require("express");
var app = express();
var routes = require("./routes/routes.js");
//Other setup code
app.use(express.static(__dirname + '/public'));
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
//Here is an example HTTP route
app.get('/home', routes.view_page);
//Other Server code
And then in routes.js
exports.view_page = function (req,res){
var customMessage = "Hello, Node is awesome";
res.render("view", {
msg:customMessage
});
};
I think your .ejs file is fine, this is a very minimal express server that works with your example:
app.js:
var express = require('express');
var app = express();
app.get('/', function (req, res) {
var customMessage = "My Message";
res.render('view.ejs', {msg:customMessage });
});
var server = app.listen(3000, function () {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
});
then use your view.ejs and put it in the sub-folder views/
I use an express app to serve an static pre-compiled jade file. which includes a external javascript file. but its not loaded while the page gets loaded. but i can access the javascript by the express static/public url. Why its not loading on the html?
app.js
var express = require('express'),
path = require('path'),
sass = require('node-sass');
var app = express();
/* default configurations */
app.set('views', __dirname + '/public');
app.engine('html', require('ejs').renderFile);
app.use(express.static(path.join(__dirname, 'public')));
/* routes */
app.get('/', function(req, res) {
res.send('Hello World');
});
app.get('/home', function(req, res) {
res.render('index.html');
});
module.exports = app;
index.html
<body>
<script type="text/javscript" src="/scripts/site.js"></script>
<script type="text/javascript">
window.onload = function() {
Site.View.init();
}
</script>
</body>
site.js
var Site = Site || {};
Site.View = {
init : function() { alert('view'); }
};
When i open the page in browser i get ReferenceError: Site is not defined
Thanks.
Add app.use('/public/js', express.static(path.join(__dirname, '/public/scripts'))); to app.js, in order to indicate the subfolders of the pulic folder;
If it still not works, change src="/scripts/site.js" to src="/public/scripts/site.js";
site.js must be inside public/scripts from your root directory.
I am not sure but both views and express static pages are gone to public directory in your code.
Use default configuration as:
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.static(path.join(__dirname, 'public')));
You may also add a route for it like this:
app.get('scripts/site.js', function(req, res){
res.send('./scripts/site.js');
}