Just starting to play with node, and having a little bit trouble on routing, I looked on the routing separation example but thought it was a little bit advance for my skill, so I did in the following way, would anyone advice on the following code
index.html
<div class="container" id="test-container">
<h1>Test</h1>
<span id="test-error"></span>
<form id="test-input2">
<input type="text" id="test"></input>
</form>
</div>
ui.js
$('#test-input').submit(function(e){
e.preventDefault();
socket.emit('route', null);
});
ui_backend.js
exports.listen = function(server){
io = socketio.listen(server);
io.set('log level', 2);
io.sockets.on('connection', function(socket){
route_testing(socket);
});
}
function route_testing(socket){
socket.on('route', function(req, res){
res.render('test', function(err, html){
});
})
}
server.js
app.get('/test', function(req, res){
res.sendfile(__dirname + '/views/test.html');
});
Edit:
The problem is that I cannot get the routing to work.
Suggestion:
You setup a route in your server.js
app.get("/test", routes.page("test"));
In your ui_backend.js
module.exports = function (view) {
return function (req, res) {
res.render(view + ".html", {
page: view
});
};
};
Just do res.render() is fine. sendfile is not what you want.
function route_testing(socket){
socket.on('route', function(req, res){
res.render('test', function(err, html){
});
})
}
with socket.on(message,callback) , there is no req,res arguments. You are mixing up express and socket.io api.
on a socket message you need to emit another socket message. socket.emit(message)
socket.on('route', function(data){
socket.emit(message,somedata);
})
You basically have a server with 2 different protocols here, websockets and classic http.
The socket.io api is pretty clear: http://socket.io/ you cant make up a different api and expect it to work.
app.get('/test', function(req, res){
res.sendfile(__dirname + '/views/test.html');
});
sends /views/test.html as an attachement. You dont want to do that,you want express to render some html template or page:
app.get('/test', function(req, res){
res.render('test');
});
should work out of the box with a default express script.
So when you want to query over http, use the express api.
when you want to send message through websockets,use socket.io api.
Related
I have the following nodejs/express js
/* GET home page. */
router.get('/', function(req, res, next) {
socket.on(channelName, message => {
//console.log(channelName, message);
});
res.render('index', {page:message, menuId:channelName});
});
How can I pass the message it was the real time data to display in index view?
In the route method, you will need to fire/emit the event, so for example
when a message hit this route all the listeners on the 'message' will call the Action :
app.post('/messages', (req, res) => {
var message = new Message(req.body);
message.save((err) =>{
if(err)
sendStatus(500);
io.emit('message', req.body);
res.sendStatus(200);
})
})
And in the client side script tag in index.html, add the following code:
var socket = io();
socket.on(‘message’, addMessages)
I'm making a node application where I need to call a function, written inside my app.js, and I need to call it from, a form, in a template, made with ejs.
i'm using node.js, express.js and ejs.
can anyone help?
You want to use ajax to interface with the server-side function:
$.get('/your_route', {data: 'goes here'}, function (res) {
console.log('callback after your node function is done')
})
You might call the function from the template by:
<form class="ajax_caller" onsubmit="do_ajax_call()">form goes here</form>
However that is not considered a good practice. This is much better:
// click event
$(document).on('submit', 'form.ajax_caller', do_ajax_call)
function do_ajax_call (e) {
e.preventDefault()
$.get('/your_route', {data: 'goes here'}, function (res) {
console.log('callback after your node function is done')
})
}
Ofcourse you will have to set up a route in express:
app.get('/your_route', function (req, res) {
finally_your_function()
res.send('finished')
});
If you don't want to use ajax, you can just set the action of the form to your ajax route, however that will redirect user to the route so you will have to handle that.
You can use regular HTML forms which submit their content to a certain URL on the server.
Example:
Add the form to HTML/EJS:
<form method="GET" action="/sampleUrl">
<input type="submit" name="submit">
</form>
Add the route to your app.js:
var express = require('express');
var app = express();
app.get('/sampleUrl', function(req, res) {
//Do something
});
I learning express recently,and want to make a tiny blog with express+mongodb+monk+ejs,below is the code I writed:
model are some js exports function to handle data:
var db = require('../model/public').db;
var contentCollection = db.get('contentcollection');
exports.getContent = function (fn) {
contentCollection.find({},{},function(err,data){
fn(data);
});
};
controller is deal with route:
var express = require('express');
var router = express.Router();
var $data = require('../model/core').$content;
var $ = require('../controller/util');
router.get('/', function(req, res, next){
$data.getContent(function(data){
res.render('content', $.extend(req.staticRes, {
article: data
}));
});
});
module.exports = router;
(in this code,"$" is a util function include a method to extend double object just like jQuery.extend do.)
view is page that be controller render:
<% include ./public/head %>
<%include ./public/header%>
<%for(var i = 0;i<article.length;i++){%>
<div class="article">
<div class="title">
<%= article[i]["title"]%>
</div>
<div class="content">
<%= article[i]["content"]%>
</div>
</div>
<%}%>
<script src="/js/content.js"></script>
<% include ./public/footer %>
what confused me is the part of model,i only can access data in a method named
xxx.find({},{},function(data){
//some handle with data
})
that result in that i only use the getContnet function like that:
router.get('/', function(req, res, next){
$data.getContent(function(data){
res.render('content', $.extend(req.staticRes, {
article: data
}));
});
});
but i only want to handle the data query from database like below's form,so I can use some function that query data form different collection:
router.get('/', function(req, res, next){
res.render('content', {
article: $data.getContent('some arguments here to query from content collection'),
user: $data.getUser('some arguments here to query from user collection')
});
});
my vocabulary is poor,thanks to google translate ;-)
anyone help?
add:
var s = contentCollection.find({},{},function(err,data){
fn(data);
});
console.log(s);
is a Promise when i console it.
OK,I find the solution by myself.
After research my colleague'code whom project based on Koa,I find the different between my code with him:it's not the fault of monk which make me confuse that i mentioned above,it's the blame of Express!
below is Koa's code style for route to render page:
yield this.render('index', {
topics: $Topic.getTopicsByTab(tab, p),
items: $Scrape.getAllTopics(tab,p)
});
and below is express's(if I'm not wrong):
router.get('/',function(){
$data.getUserInfo(function(user){
$data.getContent(function(content){
res.render('index',{
userinfo:user,
content:content
})
})
})
})
see the differenent?
Express is callback,callback,callback!
and my solution is got a dependenies named "co-express",it's said that koa also based on it,below is the code after I use co-express:
router.get('/', wrap(function *(req,res,next){
res.render('content',$.extend(req.staticRes,{
content: yield $data.getContent(),
userinfo: yield $data.getUserInfo()
}))
}));
it's looks great.
thanks myself :-)
I am learning to handle file upload in express 3.
module.exports.upload is my route handler for POST request to '/image/upload' :
var multiparty = require('multiparty');
module.exports.uploadPage = function (req, res) {
res.render('image/image', {file_content: null });
}
module.exports.upload = function (req, res) {
var form = new multiparty.Form();
form.parse(req, function(err, fields, files){
console.log('inside form parsing call back');
res.writeHead(200, {'content-type': 'text/plain'});
res.end('received upload:\n\n');
});
if(req.method == 'GET') res.render('image/image');
}
this is my form:
<form action="/image/upload" enctype="multipart/form-data" method="post">
<input type="file" name="thumbnail" multiple="multiple" />
<input type="submit"/>
</form>
the console.log('inside form parsing call back'); is never executed since nothing is logged in terminal. I am using dev setting, the POST request log is even not logged to console.
Btw, I compared my code with example here. I beleive I am doing it right, but I can be wrong.
The callback seems not to be executed in this situation. Where went wrong?
Thank you!
Let me answer my question. The above code is good, but the reason it doesn't work is because I added
app.use(express.multipart());
in app.js
then add
var multiparty = require('multiparty');
again in the controller, which is image.js
This may not be helpful to you, but the take away is that only load(require(...)) multiparty where it needs to process forms. Don't use app.use, use require as this document suggests:
multiparty on github
I'm using node.js with express and I would like to make it listen on "192.168.1.1/subdir/" instead of "192.168.1.1" how may I do without having to change all the url config in express?
express-namespace can help you:
require('express-namespace')
app.namespace('/subdir', function(){
app.get('/view', function(req, res){
res.send('/subdir/view rendered');
});
app.get('/edit', function(req, res){
res.send('/subdir/edit rendered');
});
});