Using interpolation within Node.js EJS includes - node.js

My Express app is using EJS, and my views directory looks like this:
./views
./contents
home.ejs
./includes
header.ejs
footer.ejs
layout.ejs
I'm trying to load home.ejs in my layout.ejs view conditionally based on a local variable named contents in my routes/index.js. That file looks like this:
/*
* GET home page.
*/
exports.index = function(req, res){
res.render('index', { title: 'Home', contents: 'home.ejs' });
};
Ideally I could simply write (in layout.ejs):
<% include '/contents' + contents %>
where the trailing "contents" is the local variable which contains the relative path to the body text to load.
But alas, it appears EJS always interprets the text following an include directive literally, and there is no chance for any interpolation magic to happen.
I've also tried to no avail:
<% function yieldContent(contents){ %>
<% var contentPath = 'contents/' + contents; %>
<% include contentPath %>
<% }; %>
<% loadContent(); %>
Does anyone have a creative solution for conditionally including a view based on a variable passed in routes?

I think there is no way to do this kind of dynamic includes in EJS. It might break the separation of business logic and view.
The solution can be to rendering the subtemplate in the controller, and passing its content to the layout.
For rendering subtemplate in the controller use something like this:
var ejs = require('ejs'),
, fs = require('fs')
, home = ejs.render(fs.readFileSync("contents/home.ejs", "utf-8"))

In the version 2 of EJS, the include function does it well. With it, includes are inserted at runtime so variables can be used as pathnames.
In this case, the solution may be :
<%- include('contents/' + contents) %>
The function can also have another argument if necessary :
<%- include('mypathname', {foo:"bar"}) %>
The pathname has to be relative to the template which calls the function.

Currently this hasn't been implemented into ejs but, there is this discussion and pull request that offers the functionality.
https://github.com/visionmedia/ejs/issues/93

in your render function you can include fs.readFileSync and __dirname.
Render your page with options like this
res.render('pages/'+req.file,{file_get_contents:fs.readFileSync,__dirname:__dirname});
Then you can use it in your .ejs page like this. This remains in server side.
<% var products=JSON.parse(file_get_contents(__dirname+'/web/data/products.json','utf8')) %>
You can print the data on client HTML like this.
<%- JSON.stringify(products)%>
Note : Using this method means you have fs included somewhere at the top of your script.
var fs = require('fs')

Related

Use console.log in EJS

Is it possible to use console.log in a node / ejs template? It doesn't seem to do anything when I try, even something as simple as:
<% console.log('test') %>
I've also tried:
<%= console.log('test') %>
Nothing shows up in the console.
I think you are expecting it to show in the developer console. It will not show up there.
console.log() in EJS file will show the log in the terminal where the server is running.
This worked perfectly
<% console.log('heheeh', JSON.stringify(doc, null, '\t')) %>
console.log() is working fine, but its log does not display in dev tools.
So, check your terminal first:
<% console.log("test") %>
It's perfect.
console.log(test) in ejs file will show the log in the terminal
And if you want to see test object or value in browser than try
<%= test %>
This will show objects as string
I know this is a really old thread, but I just had this issue and this is what I ended up doing:
<% var data = JSON.stringify(htmlWebpackPlugin) %>
<script>
console.log(<%= data %>)
</script>
It doesn't look pretty, but it works
Code
Output
<% console.log(posts) %>
NB: Make sure you define your variable in any other file you have eg app.js file...
let posts = [];
app.get("/", (req, res) => {
res.render("home", {
posts: posts
});
});
OUTPUT
Click me
first, Your home route inside your index.js/server.js/app.js, render a variable you want console log in another ejs file; in the code below, nposts is a variable or an array;
app.get("/",function(req,res){
res.render("home", {posts: nposts});
then in your ejs file, in this example in the home.ejs console.log in the <% %> tags
<% console.log(posts); %>
send from serve-side
let item = [arr1, arr2, arr3]
res.send("index", { item })
in client-side
example
use in script
console.log('<%- item %'>
arr1,arr2,arr3
console.log('<%- JSON.stringify( item ) '%>
["arr1","arr2","arr3"] //text
var newArray = JSON.parse('<%- JSON.stringify( item )%>')
console.log(newArray )
<% { %>
<script>console.log('hello')</script>
<% } %>
this code is work well.
create { } by <% %> from ejs.
We can add javascript code inside { }.
The simple answer would be:
If you are in your home route and you want to test any condition you would have to use ejs tags. inside the tags drop your normal console.log.
<% console.log(test) %>

Add javascript code into the rails app

Actually, I'm having trouble adding javascript code into my rails application.
I tried putting the import.js in "app/assets/javascripts" as well and it didn't work either.
I also added, //= require import at the end of application.js file but still not working.As a result the whole application got stucked.
index.html.erb
TEST
<div id = "test">
<h2>Import Statements</h2>
<%= form_tag import_samples_path, multipart: true do %>
<%= file_field_tag :file %>
<%= submit_tag "Import" %>
<% end %>
</div>
sample.coffee
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/
$( document ).ready(function() {
$("div#test").hide();
$("a").click(function(event) {
event.preventDefault();
$("div#test").toggle();
});
});
application.js
// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require bootstrap-sprockets
//= require nicetitle
Thanks in advance.
A couple of things here:
First off - you need to have a //= require_tree . inside of your application.js file. What this does is automatically requires all of the files inside of your javascripts directory.
Next, (and I'm not entirely sure that this is best practice) the way that I call javascript inside of a html.erb file is inside of a <script> tag. I'll put an example of my code below. I only very recently figured out how to call JS from inside of html in rails, so like I said this is probably not best practice, but this is how I did it.
<script language="javascript" type="text/javascript">
var counts = ['Count']
var dates = ['x']
<% #chart.datasource.datapoints.each do |c| %>
dates.push( "<%= c.date %>" )
counts.push( <%= c.count %> )
<% end %>
chart(counts, dates);
</script>
So I actually put it inside of a script tag like you saw. Hopefully this helps.

how to include dynamic html file in html page in node.js?

I have set value in variable {action:'page1.html'} after render this value in index.html layout then I want to use include dynamically page but not working.
router.get('/', function(req, res, next) {
console.log(req.query.action);
res.render('users/index', {action:'page1.html'});
});
**index.html**
<% include+"./"+action %>
Please suggest..
First of all you must have versione 2.x of EJS, then you need to include it as:
<%- include(action) %>
Ref: https://github.com/mde/ejs#includes

Pass variable to EJS include

I have a global header used in a couple of places and I was trying to define its location in a variable that could be passed when rendering a template.
Something like:
var headerLocation = 'some/location/header.ejs';
res.render( viewDir + '/index', {
header: headerLocation
} );
And in a template file:
<% include header %>
header being the value passed in with the render.
It doesn't seem to be possible but maybe I missed something so thought I'd ask here.
EDIT:
This is mentioned in comments on answers below but to summarize, this is now available in version 2 of EJS.
See here: https://github.com/mde/ejs#includes
And related discussion here: https://github.com/tj/ejs/issues/93
Here is some demo code that can accomplish dynamic includes.
View
<div flex class="main-container">
<%- include(page) %>
</div>
Router
router.get('/', function (req, res, next) {
res.render('pages/index', {
page: 'home'
});
});
This feature has been added: if it is not path (file not found), it is evaluated as variable name. https://github.com/visionmedia/ejs/pull/156
Even though its an old question, answering it for others sake.
As per the github documentation, it seems EJS has no notion of blocks, only compile-time include. Since its compile time include, you need to hardcode the location.
So you are left with passing some flags and doing if checks in the header or parse the header as html and pass it to all the templates...
Old subject, but it may help someone.
The great thing about EJS is that it is just Javascript. So something like the following should work:
<%
const fs = require('fs');
const content = fs.readFileSync(partial);
%>
<%- content %>
Hope it helps.

Display sql query result in ejs file using node express

newbie here, I want to display my sql query result into my ejs file but I don't know how to.
any help will be appreciated.
To use ejs, the Express render engine must be set.
app.engine('html', require('ejs').renderFile);
Then you can pass variables to templates a SQL query:
connection.query('SELECT 1', function (err, rows) {
res.render('file.html', {
'sql': rows
});
});
In your template, then you can use code like so:
<%= sql.property %>
and even use scripts inside tags:
<% sql.forEach(function(field){ %>
<%= field.property %>
<% }) %>
Use EJS template url and send sql results using:
.render()

Resources