knockoutjs in express using ejs - node.js

I would like to start using knockoutjs in a web app currently based on Nodejs with express using ejs view engine.
index.ejs
<% layout('layout') -%>
<!-- Jquery Include-->
<script src="/js/jquery-2.1.0.min.js"></script>
<!-- Knockout Javascript Dependency-->
<script src="/js/knockout-3.0.0.js"></script>
<script type="text/javascript">
var viewModel = {
firstName : "Bert"
};
ko.applyBindings(viewModel);
</script>
<p>First Name: <span data-bind="text: firstName"></span></p>
It appears that knockout js is loading properly however, the data-binding is not working I simply see.
First Name:
Is there a compatibility issue loading knockout in an ejs file?

There are no compatibility issues with ejs - as far as I know - however you need to call ko.applyBindings after your DOM is loaded, from the documentation:
To activate Knockout, add the following line to a block:
ko.applyBindings(myViewModel);
You can either put the script block at the bottom of your HTML
document, or you can put it at the top and wrap the contents in a
DOM-ready handler such as jQuery’s $ function.
So you need to change your template to move the ko.applyBindings at the end:
<% layout('layout') -%>
<!-- Jquery Include-->
<script src="/js/jquery-2.1.0.min.js"></script>
<!-- Knockout Javascript Dependency-->
<script src="/js/knockout-3.0.0.js"></script>
<p>First Name: <span data-bind="text: firstName"></span></p>
<script type="text/javascript">
var viewModel = {
firstName = "Bert"
};
ko.applyBindings(viewModel);
</script>
Or use the jQuery’s $ function:
<% layout('layout') -%>
<!-- Jquery Include-->
<script src="/js/jquery-2.1.0.min.js"></script>
<!-- Knockout Javascript Dependency-->
<script src="/js/knockout-3.0.0.js"></script>
<script type="text/javascript">
var viewModel = {
firstName = "Bert"
};
$(function() {
ko.applyBindings(viewModel);
});
</script>
<p>First Name: <span data-bind="text: firstName"></span></p>

Related

EJS include as wrapper

Can I include another .ejs file that will wrap the current content?
I want to have a general layout like this:
layout.js:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="header"></div>
<div id="content">
<!-- I want to "inject" my code here -->
</div>
</body>
</html>
and I want to use this template from another file, like this:
content.ejs
<% inside(layout) ? { %>
content
<% } %>
Can I do something like this?
I'm currently doing this the other way around, I call layout with a parameter include_name but it's a little inconvenient. I would like to call the relevant content.ejs which includes the generic content itself. Is this possible?
Thanks,
From EJS Documentation:
EJS does not specifically support blocks, but layouts can be
implemented by including headers and footers, like so:
<%- include('header') -%>
<h1>
Title
</h1>
<p>
My page
</p>
<%- include('footer') -%>
Although some frameworks have some facilities to deal with problem. for example Express until version 3.x had layout support and for latest versions you could use it as a stand alone npm package: express-partials
With this package in place you define a <%- body %> region in your skeleton template (layout.ejs) and when you call your desired layout (content.ejs), express will render layout.ejs with content.ejs as <%- body %> ( unless you set {layout:false} which then it only renders content.ejs):
layout.ejs
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="header"></div>
<div id="content">
<%- body %>
</div>
</body>
</html>
content.ejs
content
app.js
var express = require('express')
, partials = require('express-partials')
, app = express();
// load the express-partials middleware
app.use(partials());
app.get('/',function(req,res,next){
res.render('content.ejs')
// -> render layout.ejs with content.ejs as `body`.
})
app.listen(3000);

How to dynamically update a tool tip when using materialize

I am using materializecss in my app script add-on, When I try and add a tooltip dynamically the tip does not update with the new label. I have tried several variations and even double-checked that the tip was being changed, which it was. The problem is that it does not seem to reinitialize with the updated text.
Here is a jfiddle: https://jsfiddle.net/edlisten/grafo4su/1/
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.5/css/materialize.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.5/js/materialize.min.js"></script>
<script>
$(function() {
$('.tooltipped').tooltip({delay: 50,tooltip:"new",position:"bottom"});
});
</script>
</head>
<body>
<div class="container">
<a class="btn tooltipped">Hover me!</a>
</div>
</body>
</html>
What you can do is set an id to the anchor.
Lets say <a class="btn tooltipped" id="tooltip">Hover me!</a>
Now we can find easily the element with jquery.
var anchorElement = $('#tooltip');
Materialize has an atribute data-tooltip you need to have on the element so that the tooltip will pop out.
anchorElement.attr('data-tooltip', 'New tooltip value');
And finally we need to initialize the materialize tooltip on the element
anchorElement.tooltip();
You can play around with it and put it in a function.

CAN we do something like <% alert("TEMP") %> in EJS

I have sent a variable in node.js from res.render() function and I have to use that variable for my script in EJS templating for DOM manipulation.
From Node.js:
res.render('index', {TEMP: 'xyz'});
In the HTML:
<p>This is a HTML demo</p>
<div>
I'm the TEMP variable: <%= TEMP %> <!-- this is going to output xyz -->
<script>
var getTemp = <%= TEMP %>;
console.log(getTemp);
</script>
</div>

Connection-route of node.js taking wrong parameters informations

I've a problem with my node.js application.
I'm using the packages connection, connection-route, socket.io and ejs.
My application provides informations to the html page (connected via socket.io), these informations are managed by an ejs template.
When I reach a destination with a parameter, like http://localhost:5001/machine/:id2, something strange happens.
The connection route code is the following:
router.get('/machine/:mac_id', function (req, res, next) {
var mac_index = req.params.mac_id.slice(1,req.params.mac_id.length);
console.log(mac_index);
res.writeHead(200, { 'Content-Type': 'text/html' });
var str = mod_fs.readFileSync(mac_route + '/index.html', 'utf8') ;
var ret = mod_ejs.render(str, {
filename: mac_route,
title: "Machine Overview",
/* other informations */
});
res.end(ret);
}
The variable mac_route contains the path to the file index.html, which is loaded correctly.
The problem lies in the mac_index variable. On the console are printed 3 rows:
id2
unctions.js
query-1.9.1.js
The first row is obviously correct, the last 2 rows are obviously not correct, infact these are two javascript files (my file functions.js and the file for jquery jquery-1.9.1.js).
These files are included in the header of the index.html file.
HTML STRUCTURE:
header.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title> <%= title %> </title>
<link rel='stylesheet' href='/style.css' type="text/css"/>
<script src="http://localhost:5001/socket.io/socket.io.js"></script>
<script language="javascript" type="text/javascript" src="functions.js"></script>
<script language="javascript" type="text/javascript" src="jquery-1.9.1.js"></script>
</head>
<body>
<div id="header">
...
</div>
<div id="page">
index.html
<% include /header.html %>
<div id="commands">
...
</div>
<div id="main">
... code of the page, manage informations received ...
</div>
<% include /footer.html %>
footer.html
<div id="footer">
...
</div>
</div> <!-- Close the "page" div opened in the header //-->
</body>
</html>
I can't find where's the mistake.
Why the file's names are taken as parameter of the req object?
The normalized URL for those files is:
http://localhost:5001/machine/functions.js
http://localhost:5001/machine/jquery-1.9.1.js
Those match your route (/machine/:mac_id), so they will be handled by it.
Try including the connect.static middleware before your routes:
app.use(connect.static(__dirname));
(this assumes your Connect app is stored in the app variable and the JS files are in the same directory as your Node script; if not, change __dirname to point to the directory where the JS files are located).

ejs 'partial is not defined'

Okay I have a mostly static homepage but I wanted to have partial views that for navigation, footer ect. I'm using ejs and it looks like this:
my controller: home.js
// Dependencies
var express = require('express');
module.exports = {
get: function(req, res) {
app.set('view engine', 'ejs');
var model = {
layout:'home',
};
res.render('home');
}
};
My views directory has nav, home and footer all .ejs
Then the actual html file stripped of text would look as following.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" >
<title>Tom Jones</title>
<!-- CSS -->
<link rel="stylesheet" href="/css/home.css" type="text/css" media="screen" >
</head>
<body>
<%- partial('nav') %>
<!--content part -->
<div id="showcontainer">
<section>
</section>
</div>
<div id="maincontainer">
<section>
</section>
</div>
</body>
</html>
The Problem
When ever I test it out I run into the error partial is not defined. I tried requiring ejs but no success.
As #Pickels said, Partial was removed in 3.x. However, the most recent version of EJS provides a mechanism for including "partials", called "include":
https://github.com/visionmedia/ejs#includes
Includes are relative to the template with the include statement, for example if you have "./views/users.ejs" and "./views/user/show.ejs" you would use <% include user/show %>. The included file(s) are literally included into the template, no IO is performed after compilation, thus local variables are available to these included templates.
The following will work as a replacement for your old partial() function. You'll need to make tweaks elsewhere to support Express 3.x completely, but for the most part this seems to work well (better actually - less code and more performant).
<% include nav.ejs %> <!-- replaces your old <%- partial('nav') %> -->
Now in ejs 3.1.x
<% include('relative_filepath'); %>
Must be replaced by
<%- include('relative_filepath'); %>
Partial was removed in 3.x. It's now up to the templating engine to provide partials.

Resources