Template actual data context - node.js

I have troubles with data context;
Here is my code (unfortunatly, meteorpad is broken)
router.js(I use iron:router)
Router.configure({
layoutTemplate: 'layout'
});
Router.route('home',{
path: '/',
action: function(){
this.redirect('sections', {page: 0});
}
});
Router.route('sections', {
path: '/sections/:page',
data: function(){
var data = {};
data.params = {};
data.params.page = this.params.page?this.params.page:0;
return data;
}
});
template.html
<template name="layout">
{{>yield}}
</template>
<template name="sections">
Page: {{params.page}}
<br>
Page 0
Page 1
Page 2
<br>
<button>what page?</button>
</template>
template.js
Template.sections.onRendered(function(){
let scope = this;
$("button").on("click", function(){
alert("page: " + scope.data.params.page);
});
});
When I click button, button-handler has the scope, which had the template, when rendered, but not actual in this moment;

thanks to #user3374348
method Blaze.getData(scope.view) returns actual data context.
template.js
Template.sections.onRendered(function(){
let scope = this;
$("button").on("click", function(){
alert("page: " + Blaze.getData(scope.view).params.page);
});
});

Related

How do I have a variable available to display on my success page, after adding items to a database via a /POST route?

I would like to display the doc.id variable of a successful /POST of data to a route, on the success page that the user will be redirected to afterward. I'm trying to work out how to carry the variable teamId through to the Handlebar template page success.hbs
I've tried making it a variable, and setting up a Handlebar helper to display it, but nothing is working.
/POST route redirecting to success.hbs:
app.post('/create', (req, res) => {
var players = [];
var playerObj = {};
for (let i = 1; i < 21; i++) {
var playerObj = { playerName: req.body[`player${i}Name`], playerNumber: req.body[`player${i}Number`], playerPosition: req.body[`player${i}Position`] };
if (req.body["player" + i + "Name"] === '') {
console.log("Empty player name detected, disregarding");
} else {
players.push(playerObj);
}
}
var newTeam = new Team({
// WEB SETUP BELOW
"team.teamRoster.teamCoach": req.body.coachName,
"team.shortTeamName": req.body.teamShortName,
"team.teamName": req.body.teamName,
"team.teamRoster.players": players
});
newTeam.save().then((doc) => {
var teamId = doc.id;
console.log(teamId);
res.render('success.hbs');
console.log("Team Added");
}, (e) => {
res.status(400).send(e);
});
});
/views/success.hbs
<div class="container-fluid" id="body">
<div class="container" id="page-header">
<h1><span id="headline">Team Added Succesfully</span></h1>
<hr>
<h3><span id="subheadline">Input the following address as a JSON Data Source within vMix.</span></h3>
<span id="content">
<div class="row">
<div class="container col-md-12">
{{{teamId}}}
</div>
</div>
</span>
</div>
<hr>
</div>
I'd like a Handlebar helper to get the doc.id value of the /POST request, and store it as teamId to display on the success page. It's finding nothing at the moment.
Any help is appreciated.
Node.js can pass variables to the handlebars-view like this:
newTeam.save().then((doc) => {
var teamId = doc.id;
console.log(teamId);
res.render('success.hbs', {
teamId
});
console.log("Team Added");
}, (e) => {
res.status(400).send(e);
});

How can I pass id to the router delete method?

I have a list of data shown with a delete button as below.
<ul class="quotes">
<% for(var i=0; i<quotes.length; i++) {%>
<li class="quote" data-id= "<%= quotes[i]._id %>">
<span><%= quotes[i].name %></span> -
<span><b><%= quotes[i].price %></b></span>
<button class="delete-todo">×</button>
</li>
<% } %>
</ul>
From jQuery I am passing the id to be deleted as follow:
$('.delete-todo').on('click', function(e){
e.preventDefault();
var id = $(this).parent().data('id');
$.post('/products',{'id':id},function(data){
},'json');
});
I have a product.router.js as follows:
router.delete(':/id', product_controller.product_delete);
I am confused about how to call this delete of router and pass the id to this router method.
In NodeJS
router.delete('/products/:id', product_controller.product_delete);
and you will get in params( req.params.id) in product_controller.product_delete function
and in JQuery
$('.delete-todo').on('click', function(e){
e.preventDefault();
var id = $(this).parent().data('id');
$.ajax({
url: '/products/'+ id,
type: 'DELETE',
success: function(data) {
// your success response data here in data variable
console.log('result ', data);
}
});
});
Check this
Express JS
router.delete('/:id', product_controller.product_delete);
// If you are using router in `app.use('products', router)`
OR
router.delete('products/:id', product_controller.product_delete);
Ajax Call
$.ajax({
url: '/products/'+ id,
type: 'DELETE',
success: callback
});

React and Socket.io

I'm trying to create a simple app using ReactJS and Socket.io
In my component I want to be able to communicate with the server, but the problem is that I don't know how to do io.connect()
1.Do I need to explicitly specify the IP address like io.connect("http://myHost:7000") or is it enough to say : io.connect() ? As we can see in this piece of code :
https://github.com/DanialK/ReactJS-Realtime-Chat/blob/master/client/app.jsx
2.I do more or less the same as this code , but I receive error when I do npm start as io is undefined. I think , io is provided globally by including the socket.io script. How can I solve this problem ?
'use strict';
var React = require('react');
var socket = io.connect();
var chatWindow = React.createClass({
displayName: 'chatWindow',
propTypes: {},
getDefaultProps: function() {
return ({
messages: 0
});
},
componentDidMount: function() {
socket = this.props.io.connect();
socket.on('value', this._messageRecieve);
},
_messageRecieve: function(messages) {
this.setState({
messages: messages
});
},
getInitialState: function() {
return ({
messages: 0
});
},
_handleSend: function(){
var newValue = parseInt(this.refs.messageBox.value) + this.props.messages;
this.setState({
messages: newValue
});
socket.emit('clientMessage', { message: newValue});
},
render: function() {
var window =
<div>
<div>{this.props.messages}</div>
<input type="text" id="messageBox" refs="messageBox"></input>
<input type="button" onClick={this._handleSend} value="send" id="send"/>
</div>;
return (window);
}
});
module.exports = chatWindow;
This is the code :
https://github.com/arian-hosseinzadeh/simple-user-list
Answers:
1) No, you don't need to specify the IP, you can even use / and it will go through the default HTTP 80 port, anyway, you can find more examples on the socket.io site.
2) Require io too, remember to add socket.io-client to your package:
var React = require('react'),
io = require('socket.io-client');
Anyway, if you want to include the client script that socket.io server provides as a static file, then remember to add it into your HTML using a <script/> tag, that way you'll have io on the global scope avoiding the require part, but well, I prefer to require it.
NOW, WHAT ABOUT...
Trying my lib: https://www.npmjs.com/package/react-socket
It will handle the socket connection on mount and disconnection on unmount (the same goes for socket event listeners), give it a try and let me know.
Here you have an example:
http://coma.github.io/react-socket/
var App = React.createClass({
getInitialState: function() {
return {
tweets: []
};
},
onTweet: function(tweet) {
var tweets = this
.state
.tweets
.slice();
tweet.url = 'https://twitter.com/' + tweet.user + '/status/' + tweet.id;
tweet.at = new Date(tweet.at);
tweet.avatar = {
backgroundImage: 'url(' + tweet.img + ')'
};
tweets.unshift(tweet);
this.setState({
tweets: tweets
});
},
renderTweet: function (tweet) {
return (
<li key={tweet.id}>
<a href={tweet.url} target="_blank">
<div className="user">
<div className="avatar" style={ tweet.avatar }/>
<div className="name">{ tweet.user }</div>
</div>
<div className="text">{ tweet.text }</div>
</a>
</li>
);
},
render: function () {
return (
<div>
<ReactSocket.Socket url="http://tweets.socket.io"/>
<ReactSocket.Event name="tweet" callback={ this.onTweet }/>
<ul className="tweets">{ this.state.tweets.map(this.renderTweet) }</ul>
</div>
);
}
});
React.render(<App/>, document.body);

sails.js view does not load

I made a controller which get data from a rest api and
serializes them to .xls file.
In my web view I have a button with "Create xls data" which call my controller.
Then my controller sierialises and reload this view with the xls download link and a "Download data" button.
My view import_export_data_page.ejs:
At start button "Create xls data" is displayed.
<%
if(typeof link == 'undefined'){
%>
<button type="button" class="btn btn-primary" id="button_get_xls_file">Create xls data</button>
<%
}else {
%>
<button type="button" class="btn btn-primary"></button>
<%
}
%>
<script type="text/javascript">
$('#button_get_xls_file').click(function(){
var projectName = getCurrentServiceName(currentService);
$.get( "/api/export_xls_data", { url : currentService, projectname : projectName} ).done(function( data ) {
});
});
</script>
In my controller :
exportXLS : function(req,res)
{
var request = require('request');
var categories;
//get informations
request(url + "/places", function (error, response, body) {
categories = JSON.parse(body);
/*
* Parsing tacks 3 seconds max
*/
//if file exists delete and create file
fs.exists(fileName, function (exists) {
if(exists){
fs.unlinkSync(fileName);
}
fs.writeFile(fileName, xls, 'binary',function(err){
if(err){
console.log(err);
res.status(500);
return res.send("");
}else{
var downloadLink = req.headers.host+'/xls/'+currentProject.split(' ').join('')+'_data.xls';
console.log(downloadLink);
return res.view('import_export_data_page',{link : downloadLink});
});
});
}
}
My file is created. My link works but my view is not reloaded.
Your view is not reloaded because your making an AJAX call. There is nothing in your code to tell the page to reload the view.
I think you want to change this:
$.get( "/api/export_xls_data", { url : currentService, projectname : projectName} ).done(function( data ) {});
to:
window.location.href = '/api/export_xls_data?url=' + currentService + '&projectname=' + projectName

Nodejs EJS helper functions?

Is there a way to register helper functions to EJS templates, so that they can be called from any EJS template? So, it should work something like this.
app.js
ejs.helpers.sayHi = function(name) {
return 'Hello ' + name;
});
index.ejs
<%= sayHi('Bob') %>
Yes, in Express 3 you can add helpers to app.locals. Ex:
app.locals.somevar = "hello world";
app.locals.someHelper = function(name) {
return ("hello " + name);
}
These would be accessible inside your views like this:
<% somevar %>
<% someHelper('world') %>
Note: Express 2.5 did helpers differently.
I have another solution to this, and I think it has some advantages:
Don't polute your code exporting filters.
Access any method without the need to export them all.
Better ejs usage (no | pipes).
On your controller:
exports.index = function(req, res) {
// send your function to ejs
res.render('index', { sayHi: sayHi });
}
function sayHi(name) {
return 'Hello ' + name;
};
Now you can use sayHi function inside your ejs:
<html>
<h1><%= sayHi('Nice Monkey!') %></h1>
</html>
You can use this method to send modules to ejs, for example, you could send 'moment' module to format or parse dates.
Here's an example filter...I'm not familiar with helpers.
var ejs = require('ejs');
ejs.filters.pluralize = function(num, str){
return num == 1 ? str : str+'s';
};
<%=: items.length | pluralize:'Item' %>
Will produce "Item" if it's 1, or if 0 or > 1, produces "Items"
app.js
ejs.filters.sayHi = function(name) {
return 'Hello ' + name;
});
index.ejs
<%=: 'Bob' | sayHi %>
I am using:
In helpers/helper.js
var func = {
sayhi: function(name) {
return "Hello " + name;
}, 
foo: function(date) {
//do somethings
}    
};
module.exports = func;
In router:
router.get('/', function(req, res, next) {
res.render('home/index', {
helper: require('../helpers/helper'),
title: 'Express'
});
});
In template:
<%= helper.sayhi("Dung Vu") %>
goodluck

Resources