socket.on doesn't work outside io.sockets.on('connection,..) - javascript

I have tried to catch a message from a routing page in this way:
ROUTING PAGE
router.get('/', function(req, res, next){
var socket= req.app.get('socketio');
socket.on('Ok', () => console.log("OK"));
res.render('exercises', {title: 'Exercises', ex: values[0]});
})
APP.JS
io.sockets.on('connection', function(socket){
console.log('Connesso');
app.set('socketio', socket);
})
In order to catch an 'Ok' event from the client in the routing page, but it's doesn't work and I don't figure out why because I've passed socket with app.set
EDIT
I emit the event here:
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost:8080/');
</script>
<div id="addex" hidden>
<form name="newex" method="get">
<h1>Inserisci esercizio</h1>
<p>Nome</p>
<input id="name" name="name" type="text"></input>
<p>Descrizione</p>
<input id="description" name="description" type="text"></input>
<input type="submit"></input>
</form>
</div>
<button id="add" type="button" onclick=""> Add </button>
<h1><%= title %></h1>
<p>Welcome to <%= title %></p>
<ul>
<p>Excercises:</p>
<% ex.forEach(value => { %>
<li><%= value.name %></li>
<% }); %>
</ul>
<script type="text/javascript">
add.onclick = function(event){
addex.hidden = false;
}
newex.onsubmit = function(event){
event.preventDefault();
socket.emit('message', {name: document.getElementById('name').value, desc: document.getElementById('description').value});
}
</script>
</body>
</html>

Try to follow this example:
const socketServer = SocketService.io = socketIo(server, {
path: process.env.WEBSOCKETS_PATH || "/socket.io",
handlePreflightRequest: (req, res) => {
const headers = {
"Access-Control-Allow-Headers": "Content-Type, Authorization",
"Access-Control-Allow-Origin": req.headers.origin ? req.headers.origin : "*", // or the specific origin you want to give access to,
"Access-Control-Allow-Credentials": true,
};
res.writeHead(200, headers);
res.end();
},
});
export let socketConnection;
socketServer.on("connect", async (connection) => {
logger.log("Successfully established socket connection.");
connection.emit("connection", { code: 200, message: "Socket connection established." });
socketConnection = connection;
connection.on("my event", async (streamConnection) => {
logger.log("Successfully established socket my event.");
connection.emit("connection", { code: 200, message: "My event established, listening on 'my event' event." });
});
});
Now in some other part of code you can import 'socketConnection', and use it.

.emit is to fire an event and .on listens for event.
With that being so, In your router code by doing socket.on('Ok', () => console.log("OK")); you are trying to listen to an event named Ok.
Now to listen to that event, there has to be an event fired named Ok. In your client by doing this socket.emit('message', ...) you are firing an event named message.
In your given code I don't see if you need this message or not but summary is to listen to and event named Ok you have to socket.emit('Ok', ...) somewhere else; your client in this case.
This is the bare basic of socket.io. I suggest you check the documentations and some tutorials because it was confusing for me in the beginning as well :)
Hope that helps you!
Cheers!

Related

How to add a button with an Update function using Node and Mongoose

I have created a mongoose db with events, each event is inside a bootstrap card. I am trying to figure out a way how can I redirect admin to a page where he can update the event-card and saved to my mongoose db.
The issue I have is that I already have a form for that card with a delete action and I need to be able to have another one. What I thought is to add a link which will redirect to an update_page.ejs where admin will can make changes to the form of that event and save them.
Code for admin.ejs page
<% events.forEach( function (event) { %>
<form class="form-events" action="/delete" method="post">
<div class="card col-lg-3" style="width: 18rem;">
<img class="card-img-top">
<div class="card-body">
<h5 class="card-title"><%= event.title %></h5>
<p class="card-text"><%= event.description %></p>
<p class="card-text"><%= event.date %> </p>
<p class="card-text"><%= event.capacity %></p>
Update
<button name="deleteBtn" value="<%=event._id%>" type="submit" class="btn btn-danger">Delete</button>
</div>
</div>
<% }); %>
</form>
Currently the update button redirects here:
where is basically a creation of an event.
A simple solution I thought is just to add another button near the create page like update.
So my first problem is that how can I after redirecting from my admin.ejs to create_page.ejs
have the from completed by the event pressed otherwise the form contents will be empty, and which app.() method I must use ( POST, PATCH ) and finally is it even possible to add 2 actions to one form?
app.js code
//Create new event route.
app.post("/create_event", function (req, res) {
const event = new Event({
title: req.body.ev_title,
description: req.body.ev_desc,
date: req.body.ev_date,
capacity: req.body.ev_cap,
});
event.save(function (err) {
if (err) {
console.log(err);
} else {
res.redirect("/admin");
}
});
});
// Delete an event
app.post("/delete", function (req, res) {
const deletedItemId = req.body.deleteBtn;
Event.findByIdAndDelete(deletedItemId, function (err) {
if (!err) {
console.log("Successfully deleted");
res.redirect("/admin");
} else {
console.log(err);
}
});
});
P.S my solution for the DELETE route is correct?
I am sorry for all the specifics, but I am totally new to this and have this project deadline coming up
googled all this method but the docs seemed a bit too technical right now for me.
You can simply add a another route to node application like
// Update an event.
app.post("/update/:id", function (req, res) {
const _id = req.params.id;
const event = new Event({
title: req.body.ev_title,
description: req.body.ev_desc,
date: req.body.ev_date,
capacity: req.body.ev_cap,
});
event.findOne({ _id }, '_id title description date capacity', function (err, data) {
if (err) {
console.log(err);
} else {
res.render('path to create_data.ejs', { event : data });
}
});
});
In the create_data.ejs file, fill all the form elements with value of the event like value="<%= event.title %>".
Note : If you're making above changes in create_data.ejs file, make sure to pass a blank event property in the create_event route as well like
// Create an event.
app.post("/create", function (req, res) {
res.render('path to create_data.ejs', { event : {});
});
Now,
Add a condition on create button in create_event.ejs file like
<% if(_event.id){ %>
... Update button to save the updated event
<% }else{ %>
... Create button to create a new event
<% } %>
Finally, In your admin.ejs file change
Update
to
Update
Hope this answers your question.

Apostrophe in textarea Javascript

I create a sort of a company forum. Users can create post to share an information. To do so and at the moment, they complete a form with a basic textarea. My problem is that when they write a word with an apostrophe, the code interpret the apostrophe as single quote and it create en exception. I show you the code and an exemple below.
Html :
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
</head>
<body>
<div id="admin">
<div v-if="seenNews" id="news">
<div class="form">
<h4>Create a post</h4>
<form class="newPost" action="/newPost" method="POST">
<label id="titleLabel" for="titleInput">Title : </label>
<input type="text" id="titleInput" name="titleInput" required>
<label id="contentLabel" for="contentInput">Content : </label>
<textarea id="contentInput" name="contentInput" cols="40" rows="5" required></textarea>
<button type="submit">Create</button>
</form>
</div>
</div>
</div>
</body>
</html>
Back-end javascript :
app.js
const Server = require('./server/Server');
const express = require('express');
const DAO = require('./server/DAO');
const server = new Server();
server.start();
const dao = new DAO();
dao.connect();
server.app.post("/newPost", function(req, res) {
try {
dao.newPost(req.body.titleInput, req.body.contentInput).then(value => {
res.redirect('/Admin');
})
} catch (e) {
console.log(e);
}
})
DAO.js
const sql = require('mssql');
class DAO {
constructor() {
this.sqlConfig = {
user: 'username',
password: 'password',
server: 'SERVER',
port:port,
database: 'DB',
options: {
enableArithAbort: false,
encrypt:false
}
}
}
async newPost(title, content) {
try {
let req = 'INSERT INTO DB.dbo.[Table] (title, content) VALUES (\''+title+'\',\''+content+'\')';
console.log(req);
await sql.query(req).then(value => {
return true;
});
} catch (e) {
console.log(e);
return false;
}
}
}
As exemple, if a user create a post with this content : Ms. Smith's keys are at the reception desk, I would have this in console :
RequestError: Unclosed quotation mark after the character string ')'.
Maybe if I create a function to find en encode the character it can fix it, but I don't see how I can do so.
I finally use the JS function replace() to replace simple quote in my string by two simple quote. '' is the equivalent of js \' in sql server.
'INSERT INTO PROFACE.dbo.[Posts] (title, content) VALUES (\''+title.replace(/'/gi,"''")+'\',\''+content.replace(/'/gi,"''")+'\')'

accessing variable of node into html file

I have an index.html file and an app.js nodejs file. I have a var in app.js which is the name and want to print that variable in my index.html page
Code
var name = "Utsav";
var HTTP = require('HTTP');
var fs = require('fs');
function onRequest(req, res){
fs.readFile('index.html', function(err, data) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(data);
res.end();
});
}
<html lang="en">
<head>
<title>Enter your request</title>
</head>
<body>
<label for="Name:">Name</label><br>
<input type="text" id="req"><br>
</body>
I want the value of name from app.js to print in a text box in index.html
For displaying data in your index.html, you can pass it like this.
app.get('/profile', function(request, response) {
response.render('pages/profile', {
user : request.user
});
})
and then in the html, you can view it like this.
<div>
<form>
<fieldset>
<input type = "text" value = "<%= user.user.username %>" />
</fieldset>
</form>
</div>
Hope it helps :)

Implementing search in js

I've been trying to implement some searching features. I need the program to read search area and redirect the user to the page with results. Here's my search.ejs
<script>
function executeSearch($this) {
console.log('button clicked');
let request_data = document.getElementById('search-area').value;
console.log("Request data : " + request_data);
$.post("search", {subtitle: request_data}, function(json) {
console.log('requested access completed');
})
}
</script>
<input id="search-area" type="search" value="" placeholder="Enter movie title" />
<button onclick="executeSearch(this)" class="details-button">Search</button>
<ul class="search-list">
<% for(let i=0; i< movieList.length; i++) { %>
<li class="single-search-result">
<h3 class="text-light">
<%=movieList[i].title%>
</h3>
<br>
</li>
<% } %>
</ul>
Here's the code handling the request :
app.post('/search', (req, res) => {
movie_controller.getBySubTitle(req.body.subtitle)
.then(result => {
res.render('search', {
movieList: result
});
})
.catch(err => {
console.log(err);
res.render(500);
})});
By using console.log, I've determined that there are no issues in transferring required data, however I can't render 'search' page after getting data from getBySubtitle(). Any ideas what can be causing this? Thank you in advance.

Testing socket.io with Zombie.js across two browsers

I'm building a real time chat app using node and socket.io. Having problems trying to feature test using Zombie. The app itself is working fine in browser but test is failing with the message
AssertionError: expected '' to include 'Hello'
During debugging it seems that when Zombie presses the send button it does not fire the 'chat message' event - though it does in development.
describe('chat feature', function() {
beforeEach(function(done) {
browser1 = new Browser({
site: "http://localhost:3000"
});
browser2 = new Browser({
site: "http://localhost:3000"
});
done();
});
beforeEach(function(done) {
browser1.visit('/', done);
});
beforeEach(function(done) {
browser2.visit('/', done);
});
describe("Chat page has been rendered", function() {
beforeEach(function(done) {
browser2.pressButton('Javascript testing');
browser2.fill('.chatbox-input', 'Hello');
browser2.pressButton('Send', done);
});
it('sends chat messages between browsers', function(done) {
expect(browser1.text('li')).to.contain('Hello');
done();
});
});
});
And the HTML (dynamically loading scripts into content div using jquery)
<html>
<head>
<title>Global Code Network</title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<div class="main">
<h1>Global Code Network</h1>
<div id="content"></div>
</div>
<div class="bottom-bar">
<h2>Current requests:</h2>
<div id="join-rooms"></div>
</div>
<script id="chat-template" type="text/template">
<ul id="messages"></ul>
<form id="chatbox" action="">
<input type="text" class="chatbox-input" id="m" name="chat-input" autocomplete="off" />
<input type="submit" value="Send"></input>
</form>
</script>
<script id="end-chat-template" type="text/template"></script>
<script src="/socket.io/socket.io.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script src="/scripts/main.js"></script>
</body>
</html>
Client side JS
(function(exports) {
var socket = io();
socket.on('person joined', function(data) {
$('.bottom-bar').remove();
$('#content').html($('#chat-template').html());
$('#chatbox').submit(function(e) {
e.preventDefault();
socket.emit('chat message', {
roomID: data.roomID,
message: $('#m').val()
});
$('#m').val('');
});
socket.on('chat message', function(data) {
$('#messages').append($('<li>').text(data.message));
});
});
exports.socket = socket;
})(this);
And server side JS
io.on('connection', function(socket) {
socket.on('join room', function(data) {
socket.join(data.roomID);
io.to(data.roomID).emit('person joined', {
roomID: data.roomID
});
socket.broadcast.emit('update available rooms', {
rooms: rooms
});
});
socket.on('chat message', function(data) {
io.to(data.roomID).emit('chat message', data);
});
});
Thanks

Categories