I'm new to node js and came across this hbs module and saw it in this part code for example :
app.set('view engine', 'html');
app.engine('html', require('hbs').__express);
can anyone please explain what is hbs (handlebars - but what does it do)?
and why the second line is needed if the first already says that the files will be opened as html
Thank you!
hbs is a express.js wrapper for the handlebars.js javascript template engine. Handlebars.js is a template engine to make writing html code easier, if intrested you can look here. But handlebars.js is meant for client-side copilation(the browser compiles the templates) so you need a wrapper like hbs.
A wrapper makes it possible to use for example a client-side library in express.js and that is what hbs does. This was a little simplify, but it explains the principle.
Over to your second question, why the second line is needed. and that is because if you use the standard line:
app.set('view engine', 'hbs');
express.js looks for the view engine named hbs, but in your example:
app.set('view engine', 'html');
app.engine('html', require('hbs').__express);
express.js dosent know what to look for in case of the view engine defined as html and you have to define this view engine in the second line, so express.js knows what to look for. If you look here, you can see that it says, Express loads it internally.
Related
I am using res.sendFile() to render my HTML page but the css styles are not being rendered as well.
I trie looking online for help and saw some people suggesting the use of express.static() to turn the files folder into a static one and that would make the css render, but honestly I didn't fully understand. I don't know if the css and html need to be on the same folder or not, or even how to structure the code after using static(). Can someone help me out?
Here's a snippet of the code
const express = require('express');
const userControl = require('./controller/userControl');
const routes = express();
routes.get('/login', (req, res)=>{
res.sendFile('login.html', {root: '../pages'});
});
Here's my file structure
(https://i.stack.imgur.com/R4mLY.png)
I have a ASP.NET Core application which renders tables on the serverside, some are quite complex.
I used to use sorttable: Make all your tables sortable for make the tables sortable; now as I have included vue.js (2.0, without npm / webpack), the jquery plugin obviously does no longer work properly.
Now, before i transition fully over to 100% clientside table rendering - which I want to avoid for now, if its possible, cause its complex - is there something similar to add sorting to a rendered html with vue or is that concept that old and no longer viable in vue.js and other modern frameworks?
So, questions are:
How to make sorttable work in vue.js are (without npm / webpack)
Or how to add something like that to a already server rendered html with vue?
Looking forward and regards, Peter
Okay, got it. That was a journey :-)
Sorttable script: https://www.kryogenix.org/code/browser/sorttable/
The script:
Vue.component('date-table', {
template: '<div><slot></slot></div>',
props: ['innerHtml'],
mounted: function () {
var self = this;
sorttable.makeSortable(this.$el.firstChild);
},
beforeDestroy: function () {
}
});
The markup:
<date-table v-once>
HERE IS MY ORDINARY HTML WHICH SHOULD BE SORTED BY
"sortable.makeSortable(...."
</data-table>
In my Onsen app I have the following splitter. I am using Jade, and rendering all the other pages from the list items in html (despite the fact that they are in separate jade files) by including the files at the bottom of the page, as shown below:
body(ng-controller='...')
ons-splitter(var='mySplitter')
ons-splitter-side(var='menu' side='left' width='220px' collapse swipeable)
ons-page
ons-list
ons-list-item(ng-click="root.load('home.jade')", tappable='')
| Home
ons-list-item(ng-click="root.load('search.jade')", tappable='')
| Search
... more list items
ons-template(id='home.jade')
ons-page(ng-controller='...')
ons-toolbar
.left
ons-toolbar-button(ng-click='mySplitter.left.open()')
ons-icon(icon='md-menu')
.center
| My App
//- google maps stuff
ons-input#pac-input.controls(type='text', placeholder='Search Box')
div#map.col-md-12
ons-bottom-toolbar
.center
| MyApp
include search.jade
I believe this is a dirty shortcut, and will load the contents of search.jade (as well as every other file I include) before the user even clicks the item in the splitter.
I do not want this functionality. I would like to instead have server code in NodeJs that renders the jade files in html when they are ready to be displayed to the user. Something like this:
jade.renderFile('search.jade')
This angular code is currently how I am loading the page from the item in the splitter:
mySplitter.content.load(page)
.then(function() {
$scope.pop = page;
mySplitter.left.close();
});
However I am very confused about how to write this in a node route. Do I just abandon the splitter function in angular?
Can anyone help clarify this for me and show me a clear example of how to write the node route to render the jade files as html each time they are loaded?
Please see solution 1 of the selected answer from this stack overflow post for a reference of what exactly I am trying to do: stack overflow post
I am currently using solution 2 from that post.
I believe this is the relevant code in server.js:
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
However when I change jade to html, I receive the error:
Error: Cannot find module 'html'
All my front-end files in the views folder have .jade extensions and are written in jade.
Update
Here is how I am serving index.jade (which is in the views folder) in a file called index.js:
module.exports = function(app){
/* Get home page. */
app.get('/', function(req, res, next) {
res.render('index', { title: 'My App' });
});
}
This was my old route NodeJS route which is no longer being used because of the splitter:
// get user search page
app.get('/user/search', function(req, res, next) {
return res.render('searchForTrainer');
});
Hmm. Since your code seems relatively small I would guess that what it does may be just serving all your files from views and actually "rendering" them. So probably you are just failing to access them properly later on. Maybe you have a url like /search.html or /search (instead of /search.jade). Could you try to confirm whether you can access such a url?
Also is your index.jade file served in some other way like startingPoint: 'index.jade' or something similar or is it also located in the views folder?
Basically as long as your index file has the same treatment as your other views then everything should be fine.
Update:
With what you just provided we can see the way in which you are serving your index.
app.get('/', function(req, res, next) {
res.render('index', { title: 'Fitness App' });
});
The equivalent of that is exactly the same as what you said you had before:
app.get('/user/search', function(req, res, next) {
return res.render('searchForTrainer');
});
Here res.render is what converts your jade into html and then returns it to the client. Since the splitter is expecting html that means you shouldn't have made changes to the server when you started using it.
Here is how the process looks like:
Client | HTTP | Server
| |
content.load('page') → GET /page ↘
| | res.render('page') // convert jade to html
html is loaded ← 200 OK html content ↙
in splitter.content | |
TL;DR - if you use your old route everything should be fine. Just remember to change the page url in the splitter from search.jade to /user/search (or whatever the url for will be).
I don't know if this a really noob question, but I have seen a lot of documentation about use Express in node.js and Express. But What I see is that they always use another lenguage called "Jade" for rendering an HTML file. Why? I'd like to know if its necesary use Jade or I can render templates in Express with HTML.
No, it's not necessary to use Jade with Express. It's just a popular option since Jade is the default for generated applications and is maintained by the same developer as Express.
They also tend to stay up-to-date with each other, such as the addition of template inheritance in jade as express dropped support for layouts.
But, there are a number of other view engines that offer built-in support for Express. And, the consolidate project can be the mediator/glue so you have even more options:
atpl
dust
eco
ect
ejs
haml
haml-coffee
handlebars
hogan
jade
jazz
jqtpl
JUST
liquor
mustache
QEJS
swig
templayed
toffee
underscore
walrus
whiskers
Note: I believe I misunderstood your question and answered too broadly at first. But, leaving the rest of what I wrote below in case it's still useful.
It's not necessary to use a view engine with Express, but can be helpful.
Express can simply .send() a value as the response:
res.send(new Buffer('whoop'));
res.send({ some: 'json' });
res.send('some html');
But, a view engine like Jade can help with generating more complex, data-driven content from a view/template. They can also help to keep your project organized by intent (separation of concerns), since views are typically kept in their own files.
Albeit, a view engine is necessary if you want to use res.render(). This method depends on the 'view engine' application setting or that you've configured an app.engine().
app.set('view engine', 'jade'); // or ejs, swig, etc.
# ...
res.render('a-view'); // looks for `a-view.jade` based on `'view engine'`
app.engine('jade', require('consolidate').jade);
# ...
res.render('a-view.jade'); // matches the extension to the `.engine()`
If you do decide to use Jade, there are multiple ways of inserting your data, including placing raw HTML in an element in your jade file. You can also insert fragments of HTML if you manually bypass the sanitizers with !{ locals.someHtmlString }
You can check out a demo of the below Jade code (albeit without passing in the locals variables) here: http://cssdeck.com/labs/qkkrzfes
//app.js
app.get('/', function(req, res){
locals.someData = {foo:'Bar'};
locals.someHTML = '<span>hello</span>'
res.render('someTemplate');
//someTemplate.jade
!!!
html
head
body
p.someClass This is plain text that goes in the paragraph
p#someId You can insert data into the text: #{locals.someData.foo}
p <a href='/'>You can just slap HTML in willy nilly</a>
p HTML is escaped by default: #{locals.someHTML}
p Escape HTML with \!{}: !{locals.someHTML}
pre
code=JSON.stringify(locals.someData, null, 2)
I was wondering if its possible to render the layout of an express application once using node.js and express. I want to have a stream playing on the layout page but I fear it will stop every time i want to render to the blocks I've declared.
Simple ajax example:
$.get('url', function(response){
$('#divToUpdateId').html(response);
});
Or this is the same:
$('#divToUpdateId').load('url');