Node JS + Express : Render subviews in a main view - javascript

I've got a page which is "Google Card" designed. I want to render some views on the cards of this main page.
The Cards interface looks like this:
Because there can be many cards, I organized my project in modules.
(BTW, if you know a framework thats fits more my project than Express does, can you tell it to me? :) )
I'm using Node.js with the Express Framework. My directory structures is this:
|-app
|--modules
|---weather
|---index.js
|----views
|-----weather.jade
|--views
|--config.js
|--server.js
|-public
|--assets
|---img
|---css
|---...
Here is some of my current code:
server.js:
var express = require('express');
var app = express();
app.use("/public", express.static(__dirname + '/../public'));
app.set('view engine', 'jade');
Board = {};
Board.modules = {};
Board.modules.weather = require('./modules/weather');
app.use(Board.modules.sticks);
app.get('/', function(req,res){
tpl = {};
tpl.modules = Board.modules;
console.log(tpl);
res.render(__dirname + '/views/board.jade', tpl);
});
app.listen(8080);
board.jade (the main page)
doctype html
html(lang="fr")
head
meta(charset="utf-8")
title Board
block stylesheets
link(rel="stylesheet", href="/public/assets/css/reset.css")
link(rel="stylesheet", href="/public/assets/css/board.css")
body
// Background
div.bg
// Header
header.topinfo
span.left.ip
| 192.168.31.11
span.center.logo
span.logo
span.logo-baseline
span.right.time
| 13:37
// Modules
ul
each val in modules
li= val
block scripts
script(src="/public/assets/bower_components/jquery/dist/jquery.min.js")
script(src="/public/assets/lib/jquery-taphold/taphold.js")
script(src="/public/assets/lib/background-check/background-check.min.js")
script(src="/public/assets/bower_components/masonry/dist/masonry.pkgd.min.js")
script(src="/public/assets/js/app.js")
And the modules/weather/index.js
var express = require('express');
var app = module.exports = express();
app.get('/', function(req,res){
res.render(__dirname + '/views/sticks.jade');
});
I think the purpose would be like getting the result of the app.get('/') of modules/weather/index.js, but without calling the route, to after insert the result of the rendering into the main view, but I don't know how to do that keeping the modularity of my code...

First, pass your main app to your modules, don't create 2 express apps, you can handle the rest using routes.
You should create a small API and use AJAX calls to fill up your main view :
On the server side :
app.get('/weather', function(req,res){
res.render(__dirname + '/views/sticks.jade');
});
Client jade:
div#weather
Client JS (using jQuery):
$.ajax({ url: '/weather',
type: 'get',
success: function(view) {
$('#weather').html(view);
}
});

#xShirase
First, pass your main app to your modules, don't create 2 express apps
As far as I know, modules in node are cached, meaning, that when you require express in sub-files, you actually get exactly the same instance as in the main app.js/server.js. So passing app doesn't improve anything, but imo makes it a tiny bit uglier.

Related

How do I make Node.js reference the CSS for my HTML

I am trying to create a Turn Based strategy game like EU4 in JS. I would like to include multiplayer functionality but I want to understand why this keeps happening: When I run my app through node it seems to be that it only shows the bare HTML and not the CSS. Please help.
Code Below:
var express = require('express')
var app = express()
var serv = require('http').Server(app)
var port = 2000
app.get('/', function(req, res) {
res.sendFile(__dirname + '/client/index.html')
})
app.use('/client', express.static(__dirname + '/client'))
serv.listen(port)
console.log('Colonial Warfare server => initialized!')
console.log('CWserver HostPort: ' + port)
var io = require('socket.io') (serv,{})
io.sockets.on('connection', function(socket) {
console.log('socket connection')
})
When your browser send the http request "/" you return your html that links to "/css/gameStyle.css".
You can either move your css folder to the client folder and change the link to "/client/css/gameStyle.css".
Or you can serve your css folder on the node app app.use(express.static('css'))
You need to serve the static CSS files by replacing the get for your index.html with the following line:
app.use(express.static('public'))
Change 'public' to 'client' if the CSS is next to your index.HTML.
Details here:
https://expressjs.com/en/starter/static-files.html
--EDIT--
As the index.html includes the css like "/css/filename.css" you have to host it like this:
app.use(express.static('css'))
or you change the references to your stylesheets to /client/css/filename.css in your html file.
Whenever you access an (for express) unknown path, express returns the index.html file.

Serving static files in Express with mustache templating

I'm trying to serve a folder of static mustache files from Express, but can't seem to figure out how to get it working. Say I just have an object of data like
{
a: 'Hello :)'
b: 'Goodbye :('
}
And two files,
public/a.html
<div>{{a}}</div>
public/b.html
<div>{{b}}</div>
How could I get express setup to where it serves any arbitrary number of static html files and replaces the templated parts with just my one big object? Thanks!
Static files are usually only called static when they are not processed in any way before sending to user.
What you're trying to achieve is a typical templating system. You can just follow instructions in the plugin:
var mustacheExpress = require('mustache-express');
// Register '.html' extension with The Mustache Express
app.engine('html', mustacheExpress());
app.set('view engine', 'mustache');
app.set('views', __dirname + '/views'); // you can change '/views' to '/public',
// but I recommend moving your templates to a directory
// with no outside access for security reasons
app.get('/', function (req, res) {
res.render('a');
});
Also consider using Handlebars, it's often more convenient to use than Mustache. You can find a list of differences in this question.
You can use mustachejs just like pug in express by setting mustache as view engine and defining its working like below code:
//required files
const fs = require("fs")
const mustache = require("mustache")
// To set functioning of mustachejs view engine
app.engine('html', function (filePath, options, callback) {
fs.readFile(filePath, function (err, content) {
if(err)
return callback(err)
var rendered = mustache.to_html(content.toString(),options);
return callback(null, rendered)
});
});
// Setting mustachejs as view engine
app.set('views',path.join(__dirname,'views'));
app.set('view engine','html');
//rendering example for response
app.get('/',(req,res)=>{
res.render('index',{data:'Sample Data'});
});
I modify zlumer's answer a little bit and the following code works fine for me.
const express = require('express');
const app = express();
const mustacheExpress = require('mustache-express');
app.engine('html', mustacheExpress());
app.set('view engine', 'html');
app.set('views', __dirname + '/views');
app.get('/', function(req, res) {
const data = {
hello: 'world',
foo: 'bar'
};
res.render('test', data);
});
app.listen(3000, () => {
console.log('Server running at http://localhost:3000/');
});
Please check https://github.com/HemingwayLee/sample-mustache-express
and feel free to clone and modify it.
You should not include your html files in the public directory. Public Directory should contain only images, javascript and css files.
Though there are many ways to structure the node/express application, but you can find one good way using Express Generator.
http://expressjs.com/en/starter/generator.html
If you use this, it will create the app structure for you which clearly explains how you should keep you static files.

Can I add multiple modules to nodeJS?

I am new to NodeJS. What I wanted to know is, can I like call 2 JS files using NodeJS & ExpressJS. Basically I want to have 2 seperate files so I can work on one and my partner can work on another one. So I want Server.js to call one file which contains some part of my REST API and other one contains rest of the function.
|--NodeModules[etc..]
|--Server.js
|--Rest/
| |--RestAPI1.js
| |--RestAPI2.js
It will be really helpful in the development of my project, if this is possible.
You can define routes in different files like this:
Server.js
var express = require('express')
var router1 = require("./routers/router1");
var app = express();
.....
app.use("/user", router1);
Router1.js
var router = require("express").Router();
router.get("/", function(req, res) {
...
});
module.exports = router;

why do I get Error: ENOENT open error when trying to render a doT.js view

I am trying out doT.js for the first time and have written a very basic server setup:
'use strict';
var express = require('express');
var app = express();
var doT = require('express-dot');
var pub = __dirname+'/public';
var vws = __dirname+'/views';
app.set('views', vws);
app.set('view engine', 'dot');
app.engine('html', doT.__express);
app.use('/css',express.static(pub + '/css'));
app.use('/img',express.static(pub + '/imgs'));
app.use('/js',express.static(pub + '/js'));
app.get('/', function(req, res){
res.render(vws + '/index.html', { title: 'dynamic title' });
});
app.listen(8080);
console.log('Server running on port 8080');
When I run the server and goto myaddress:8080 I get the following error:
Error: ENOENT, open '/home/myproject/views/layout.html'
If I try calling index.html with res.sendFile it works (although of course I can't pass variables that way)
res.sendFile(vws + '/index.html')
Where am I going wrong?
Why am i getting an error which seems to relate to a failed attempt at opening "layout.html" when no example I have seen mentions such a file?
I need to use res.render in order to pass variables to the template, but all the examples I have found do it the same way I tried in my first attempt.
dot.js isn't yet integrated with express 4.0's view engine middleware hook.
Swig is a similar application that is. It isn't quite as fast as dot.js, but for me it has a great balance of speed and features with an extremely intuitive syntax.
Full disclosure: I like swig.

Basic webserver with node.js and express for serving html file and assets

I'm making some frontend experiments and I'd like to have a very basic webserver to quickly start a project and serve the files (one index.html file + some css/js/img files). So I'm trying to make something with node.js and express, I played with both already, but I don't want to use a render engine this time since I'll have only a single static file, with this code I get the html file but not the assets (error 404):
var express = require('express'),
app = express.createServer();
app.configure(function(){
app.use(express.static(__dirname + '/static'));
});
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
app.listen(3000);
Is there a simple way to do it (in one file if possible) or Express requires the use of a view and render engine ?
I came across this because I have a similar situation. I don't need or like templates. Anything you put in the public/ directory under express gets served as static content (Just like Apache). So I placed my index.html there and used sendfile to handle requests with no file (eg: GET http://mysite/):
app.get('/', function(req,res) {
res.sendfile('public/index.html');
});
Following code worked for me.
var express = require('express'),
app = express(),
http = require('http'),
httpServer = http.Server(app);
app.use(express.static(__dirname + '/folder_containing_assets_OR_scripts'));
app.get('/', function(req, res) {
res.sendfile(__dirname + '/index.html');
});
app.listen(3000);
this loads page with assets
You could use a solution like this in node.js (link no longer works), as I've blogged about before.
The summarise, install connect with npm install connect.
Then paste this code into a file called server.js in the same folder as your HTML/CSS/JS files.
var util = require('util'),
connect = require('connect'),
port = 1337;
connect.createServer(connect.static(__dirname)).listen(port);
util.puts('Listening on ' + port + '...');
util.puts('Press Ctrl + C to stop.');
Now navigate to that folder in your terminal and run node server.js, this will give you a temporary web server at http://localhost:1337
Thank you to original posters, but their answers are a bit outdated now. It's very, very simple to do. A basic setup looks like this:
const express = require("express");
const app = express();
const dir = `${__dirname}/public/`;
app.get("/", (req, res) => {
res.sendFile(dir + "index.html");
});
app.get("/contact", (req, res) => {
res.sendFile(dir + "contact.html");
});
// Serve a 404 page on all other accessed routes, or redirect to specific page
app.get("*", (req, res) => {
// res.sendFile(dir + "404.html");
// res.redirect("/");
});
app.listen(3000);
The above example is if you want to serve individual HTML files. If you were serving a single page JS app, this would work.
const express = require("express");
const app = express();
const dir = `${__dirname}/public/`;
app.get("*", (req, res) => {
res.sendFile(dir + "index.html");
});
app.listen(3000);
If you need to serve other static assets from within a folder, you can add something like this before you start defining the routes:
app.use(express.static('public'))
Let's say you have a js folder inside public like: public/js. You could include any of those files inside of your html files using relative paths. For example, let's say /contact needs a contact.js file. In your contact.html file, you can include the script as easy as:
<script src="./js/contact.js"></script>
Building off of that example, you can do the same with css, images etc.
<img src="./images/rofl-waffle.png" />
<link rel="stylesheet" href="./css/o-rly-owl.css" />
Hope this helps everyone from the future out.

Categories

Resources