I am using Node.js and ExpressJS 3.0. Moving to 3.0, I found that partials were no longer supported and subsequently found express-partials to provide similar functionality.
Looking at the example on the GitHub page, I find this:
app.get('/',function(req,res,next){
res.render('index.ejs')
// -> render layout.ejs with index.ejs as `body`.
})
This is fine, but what if I have a layout that depends on multiple partials? That is, what if I have a block in the layout.ejs file for the header, one for the content, and one for the footer? For example, what if I use one template file for the entire web application, but different kinds of users have different headers, content blocks, and footers?
Looking at the limited documentation of express-partials, I cannot find this functionality. I was expecting something like this:
app.get('/', function (req, res) {
res.render({header: 'header1.ejs', content: 'some_file.ejs', footer: 'footer1.ejs'});
// -> render layout.ejs with header1.ejs as `header`, some_file.ejs as `content, and footer.ejs as `footer
});
How can I achieve this functionality?
I'd suggest you to use ejs includes + switches
Sorry, I'm not familliar with ejs syntax, so – jade, but the essense is the same:
app.get('/', function (req, res) {
res.render('index', {
header: 'header1',
, content: 'content1',
, footer: 'footer1'
});
});
index.jade
===========
//- header
case header
when "header1":
include "includes/header1"
when "header2":
include "includes/header2"
...
case content
when "content1":
include "includes/some_file1"
when "content2":
include "includes/some_file2"
....
Related
I'm looking to have URLs for each username. However, the only way I've figured out how to do this is by using search queries (? question marks). For example, in Node.js I am getting the 'location.search' tag, which returns whatever is after the '?' in www.domain.com/users.html?USERNAME. However, I would like to have it where I can use www.domain.com/users/USERNAME.
I am using Firebase and Node.js
It depends on how you are generating the content.
A couple of methods that come to mind:
getting the username from the URL in a node.js
using rewrites in firebase hosting
Method 1:
If you are using some kind of server-side rendering, you can just get the username from the URL and dynamically serve the content. Express example:
app.get('/user/:username', function(req , res){
res.send("This is the profile for: " + req.params.username);
});
Method 2:
If you serve the same HTML file for every user and populate it with user data on the client, you can use rewrites in your firebase hosting config:
{
"hosting": {
"rewrites": [
{
"source": "/user/*",
"destination": "/user/index.html"
}
]
}
}
This rewrites domain.com/user/username/ to domain.com/user/index.html.
Note: It does not rewrite domain.com/user/username/otherpage/. To do that you will need to add the rewrite:
{
"source": "/user/*/otherpage/",
"destination": "/path/to/otherpage/"
}
Note: If you use this method look out for 404 errors if you reference resources using relative paths. For example imagine this was a HTML file in /user/:
<!-- inside of /user/index.html -->
<script src="javascript.js"></script>
This path will be /users/username/javascript.js and may return index.html, which is a problem. To fix this, use an absolute path:
<!-- inside of /user/index.html -->
<script src="/user/javascript.js"></script>
I am new to the ExpressJS and Jade game, as like today new. I can't figure out how to render data into a div identified by its id attribute. Here is my sample Jade file:
extends layout
block content
div
h1= title
div(id="content", class="main")
I want to pass the data into the div with id Content. Here is the snippet of my ExpressJS file:
...
router.get('/', function(req, res, next) {
res.render('index', { title: 'Hello World!' });
res.render('index', { content: 'Wazzzaaapp' });
});
...
I'm able to display the title Hello world but not the Wazzzaaapp.
Sample screenshot of what I got:
Is this possible to do in render or am I missing something?
I'm not sure if this is the correct or actual answer, but I got it solved by adding (in the Jade/ Pug file of course) either the placeholder #{var_name} or = var_name as:
div(id="content", class="main")= content
OR
div(id="content", class="main") #{content}
either one works and shows the Wazzzaaapp output as intended:
Hope this solution helps others!
I've been developing a mean.js application. I have an admin theme that I'm trying to integrate with the existing application.
My question is
Can we have multiple Server Layouts, ? If the logged-in user is Regular User, use layout-1 if the user is Admin use layout-2
If we cannot have multiple server layout (I presume it isn't possible). Is there any way to detect the params or scope variable in the Angular Client App and dynamically load a partial inside the main Layout.
Let say I have an Index.html file, if the intended route is Dashboard, I just replace a section of the page view, ( Ruby on Rails Developers would know this)
UPDATE 1 :
I've created 2 files with my required Admin Index, and Layout files.
admin.index.server.view.html
and
admin.layout.server.view.html
I've also added the following code in my core.server.routes.js
module.exports = function(app) {
// Root routing
var core = require('../../app/controllers/core');
app.route('/').get(core.index);
app.route('/admin/').get(core.adminIndex);
};
I've also added the following code in my core.server.controller.js
exports.adminIndex = function(req, res) {
res.render('admin.index', {
user: req.user || null
});
};
and when I hit localhost:3000/admin/ I get Error: Cannot find module 'index'
Rename the two view files from admin.index.server.view.html and admin.layout.server.view.html to admin-index.server.view.html and admin-index.server.view.html respectively.
Also, change this line in your core.server.controller.js file;
res.render('admin.index', {
to this;
res.render('admin-index', {
Questions
How to serve javascript file dynamically? Specifically, the scripts maintain most of its body but with some variables changable (imagine HTML Jade template, but this is for pure javascript).
Scenario
When user or browser (http GET in general) visits /file.js passing parameter api, e.g. /file.js?api=123456, I would like to output pure javascript where I can take that 123456 and put in inside of my code, dynamically. Content-Type is application/javascript.
Sample:
var api = #{req.query.api}; //Pseudo
//The rest of my javascripts template
...
From my main .js file, I have set up the route:
app.get( '/file.js', function( req, res ) {
//Pseudo code that I would like to achieve
var name = req.query.name;
res.render( 'out_put_javascript_file_from_jade_file.jade', { name: name } );
});
So when a person visits /file.js, the script file will be rendered differently based on the parameter api passed in the URL. The only possible dynamic way I can think of is using Jade, but it doesn't allow pure javascript template. I believe there must be other solutions.
Please excuse my explanation. The problem is somewhat like this: How to generate a pure JavaScript file with Jade
If you want to do something quick and dirty, then you can do something like this (based on your example in the comments).
App init - read the .js template file and cache it:
// this should be async, but hey, not teaching you that part here yet
var fileJs = fs.readFileSync('file.js.template');
File.js:
(function() {
$(window).on('load', function() {
alert('Your api key is API_KEY_CONST');
});
})();
Request:
GET /api/file.js?key=123
Router:
app.get('/api/file.js', function(req, res) {
var key = req.query.key;
var key = fetchKeyFromDBSync(); // just to make it easier here, no async.
var out = fileJs.replace(API_KEY_CONST, key);
res.setHeader('content-type', 'text/javascript');
res.write(out);
res.end();
});
Now, this is really dumb and you should not try it at home, but it simply demonstrates how to do what you wanted.
Edit:
Depending on the file length, you might perform a bit better if you put the chunks of the file into an array, like:
var fileChunks = ['(function(){ blablabla;', 'var myAPIKey=', 'KEY_PLACEHOLDER', '; alert (myAPIKey);', '})()']
So later when you're resolving it with the real API key, you join the file.
fileChunks[2] = '12345';
var responseData = fileChunks.join('');
res.write(responseData);
But your last-accessed api key is then held in an array. Not quite future proof, but it shouls work if you need something quick.
Here's the situation: I use Node.js as my backend, and use markdown to edit and post my blog article. And when a client requests the specific URL, such as http://www.example.com/blog/article_1, I returned the blog contents from Node.js with some template like ejs, which would be something like the follows:
app.get("/blog/article1", function(req, res) {
var article = something // this is a valid HTML converted from a markdown file
res.render("article1", {
title: "my blog article 1",
article: article
});
});
In the above code, I render article.ejs with title and article variable. The article variable is a valid HTML to be injected to the ejs template. So far, it' fine.
However, if I want to display a HTML table which is written in the original markdown file, with Bootstrap 3's responsive table functionality, (i.e. <div class="table-responsive"><table class="table">...actual table...</table></div>), how can I do it? Right now the table in my markdown file is just a markdown file, and I don't think that it's the best idea to just modify all of my markdown files on which I insert or wrap with the <div class="table-responsive">...</div> line; the files might also be used in a situation other than Bootstrap.
In other words, is it feasible to dynamically or programmatically inject the responsive functionality to the table once the template is returned by Node.js? And is it also feasible to inject the responsive table functionality selectively? (in other words choose arbitrarily some tables that I want to add the responsive function?)
Continuing on from the comments: It's actually not that difficult to fork and modify a project. The faster you can get used to working with open source libraries the better your experience will be with Node. Things move pretty quickly in the Node world, and sometimes things won't work like they are expected to. You can either wait around for a fix, or roll up your sleeves and pitch in.
I found a way to update the markdown templates using their addTemplate method. However the version of Marked the project is using (2.8) doesn't support custom templates. I've forked the repository and updated the version of marked as well as fixed the issues this caused with the tests. I also added a restriction to prevent it from using Express 4 which breaks all the tests. I submitted these as a pull request to the original repo, but in the mean time you could use my version to write something like the following.
untested
var
express = require('express'),
app = express(),
Poet = require('poet'),
marked = require('marked'),
renderer = new marked.Renderer();
renderer.table = function(header, body) {
return '<div class="table-responsive"><table class="table">' + header + body + '</table></div>';
}
var poet = Poet(app, {
posts: './_posts/',
postsPerPage: 5,
metaFormat: 'json'
});
poet.addTemplate({ ext: 'markdown', fn: function(s) {
return marked(s);
}});
Alternatively, if all you're using poet for is the markdown conversion, you might as well use marked directly and cut out the dependency on poet.