2

I'm having a go with the socket.io https://socket.io/get-started/chat, but my problem is that when i send message then the message cant automatically into chat box. i need to reload the page to view the chat that i sent. So how to make the chat automatically insert to chat box?. i already implement into my project. i already used socket.emit as you can see at then html file. is there the right way to put it?

server.js

var express = require('express');
var env = require('dotenv').config()
var ejs = require('ejs');
var path = require('path');
var app = express();
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var session = require('express-session');
const MongoDBStore = require('connect-mongodb-session')(session)
const cookieParser = require('cookie-parser')

var http = require('http').Server(app);
var io = require('socket.io')(http);
var cors = require('cors')


app.use(cors())
app.use(cookieParser());

// mongodb://localhost:27017 127.0.0.1:27017
mongoose.set('strictQuery', true);
mongoose.connect('mongodb://127.0.0.1:27017/findaprofessional', {
  useNewUrlParser: true,
  useUnifiedTopology: true
}, (err) => {
  if (!err) {
    console.log('MongoDB Connection Succeeded.');
  } else {
    console.log('Error in DB connection : ' + err);
  }
});

var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function () {
});

const oneDay = 1000 * 60 * 60 * 24;
app.use(session({
  secret: 'work hard',
  saveUninitialized:true,
    cookie: { maxAge: oneDay },
    resave: true
}));

// ni lain
app.set("view engine", "ejs")

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

app.use('/css', express.static(path.resolve(__dirname, "asset/css")))
app.use('/img', express.static(path.resolve(__dirname, "asset/img")))
app.use('/js', express.static(path.resolve(__dirname, "asset/js")))
app.use('/vendor', express.static(path.resolve(__dirname, "asset/vendor")))
app.use('/lib', express.static(path.resolve(__dirname, "asset/lib")))
app.use('/scss', express.static(path.resolve(__dirname, "asset/scss")))
app.use('/pic', express.static(path.resolve(__dirname, "asset/img/pic")))



var index = require('./routes/index');
const { Socket } = require('socket.io');
app.use('/', index);

// catch 404 and forward to error handler
app.use(function (req, res, next) {
  var err = new Error('File Not Found');
  err.status = 404;
  next(err);
});

// error handler
// define as the last app.use callback
app.use(function (err, req, res, next) {
  res.status(err.status || 500);
  res.send(err.message);
});

io.on('connection', () =>{
  console.log('a user is connected')
  io.on("disconnect", function () {
    console.log("user disconnected");
  });
})


var server = http.listen(3000, () => {
  console.log('Server is started on http://127.0.0.1:'+ server.address().port);
});



routing

// user chat
var http = require('http').Server(router);
var io = require('socket.io')(http);

// Render Message
router.get('/messages/:id', async function (req, res, next) {
    user = await User.findOne({_id: req.session.userId},  {username: 1})
    return res.render("user/messages.ejs", {user: user, booking: req.params.id});
});


// Display Message from DB
router.get('/messageslist/:booking', (req, res) => {
    Message.find({booking: req.params.booking})
    .populate({
        path: "pro",
        model: Pro,
    }).populate({
        path: "user",
        model: User,
    }).exec().then((data) => {
        res.json(data)
    })
    
})


router.get('/messages', (req, res) => {
    Message.find({}, (err, messages) => {
        res.send(messages);
    })
})


router.post('/messages', async (req, res) => {
    const {booking, user, message} = req.body

    try {
        var msg = new Message({
            booking: booking,
            message: message,
            user: user
        });

        var savedMessage = await msg.save()
        console.log('saved');

        var censored = await Message.findOne({
            message: 'badword'
        });
        if (censored)
            await Message.remove({
                _id: censored.id
            })
        else
            io.emit('message', req.body);
        res.sendStatus(200);
    } catch (error) {
        res.sendStatus(500);
        return console.log('error', error);
    } finally {
        console.log('Message Posted')
    }

})

HTML

<!DOCTYPE html>
<html lang="en">


<%- include("../header.ejs") %>

<head>

  <link href="/css/sb-admin-2.min.css" rel="stylesheet">


  <link href="/css/chat.css" rel="stylesheet">

  <script src="https://code.jquery.com/jquery-3.2.1.min.js" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js"
    integrity="sha384-b/U6ypiBEHpOf/4+1nzFpr53nxSS+GLCkfwBdFNTxtclqqenISfwAzpKaMNFNmj4" crossorigin="anonymous">
  </script>

  </script>
  <script src="/socket.io/socket.io.js"></script>
</head>


</head>


        <!-- start here! -->

        <section class="msger" style="margin: auto;">
          <header class="msger-header">
            <div class="msger-header-title">
              <i class="fas fa-comment-alt"></i> Chat
            </div>
            <div class="msger-header-options">
              <span><i class="fas fa-cog"></i></span>
            </div>
          </header>

          <main class="msger-chat">

          </main>

          <form class="msger-inputarea">
            <input type="hidden" name="booking" value="<%= booking %>">
            <input type="hidden" id="name" class="form-control" readonly placeholder="Name"
              value="<%= user.username %>">
            <input type="text" name="user" value="<%= user._id %>">
            <input id="message" type="text" class="msger-input" placeholder="Enter your message...">
            <button id="send" type="submit" class="msger-send-btn">Send</button>
          </form>
        </section>
        <!-- End of Main Content -->
      </div>
      <!-- End of Content Wrapper -->

    </div>
    <!-- End of Page Wrapper -->
    <!-- Scroll to Top Button-->
    <a class="scroll-to-top rounded" href="#page-top">
      <i class="fas fa-angle-up"></i>
    </a>

  </div>
  <!-- End of Main Content -->

  </div>
  <!-- End of Content Wrapper -->
  </div>
  <!-- End of Page Wrapper -->



  <!-- Bootstrap core JavaScript-->
  <script src="/vendor/jquery/jquery.min.js"></script>
  <script src="/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>

  <!-- Core plugin JavaScript-->
  <script src="/vendor/jquery-easing/jquery.easing.min.js"></script>

  <!-- Custom scripts for all pages-->
  <script src="/js/sb-admin-2.min.js"></script>

  <!-- Page level plugins -->
  <script src="/vendor/datatables/jquery.dataTables.min.js"></script>
  <script src="/vendor/datatables/dataTables.bootstrap4.min.js"></script>

  <!-- Page level custom scripts -->
  <script src="/js/demo/datatables-demo.js"></script>

  <script type="text/javascript" src="/js/mdb.min.js"></script>
  <!-- Custom scripts -->
  <script>
    var socket = io();
    $(() => {
      $("#send").click(() => {
        sendMessage({
          booking: $("input[name=booking]").val(),
          user: $("input[name=user]").val(),
          message: $("#message").val()
        });
      })
      getMessages()
    })
    socket.on('message', addMessages)
    socket.on('message', getMessages)
    socket.emit('message', getMessages)
    socket.emit('message', addMessages)

    function addMessages(message) {
      if(message.user && message.user != '') {
        if($("input[name=user]").val() == message.user._id) { 
        html = '<div class="msg right-msg"><div class="msg-img" style="background-image: url('+message.user.image +')"></div>'
        html += '<div class="msg-bubble"><div class="msg-info"><div class="msg-info-name">' + message.user.username + '</div><div class="msg-info-time">' + message.createdAt + '</div></div>'
        }
      }
       else {
        html = '<div class="msg left-msg"><div class="msg-img" style="background-image: url('+message.pro.image +')"></div>'
        html += '<div class="msg-bubble"><div class="msg-info"><div class="msg-info-name">' + message.pro.username + '</div><div class="msg-info-time">' + message.createdAt + '</div></div>'
      }
      html += '<div class="msg-text">' + message.message + '</div></div></div>'
      $(".msger-chat").append(html)

    }

    function getMessages() {

      $.get('http://localhost:3000/messageslist/<%=booking%>', (data) => {
        data.forEach(addMessages);
      })

    }

    function sendMessage(message) {
      $.post('http://localhost:3000/messages', message)
    }
  </script>



i tried to automatically get the message without reload the page but it doenst work. Can anyone see where the problem is?

Wan Ilhami
  • 23
  • 4

2 Answers2

0

From what I know, the default behavior when you click a button with type submit inside a form, it tries to reload the page even though you haven't defined any function or other page for it to go.

You would have to get the submit event from the form and use the preventDefault() funciton for this event, check out this thread for more info:

JavaScript code to stop form submission

So you would stop the form submission and then get new messages for the page, executing the javascript to add the new messages to the page by manipulating the DOM.

  • the javascript that you mention cant be use because it doenst refresh the data. the link given is to stop form submission but my problem is to get message automatically by not reloading the page – Wan Ilhami Jan 31 '23 at 08:33
  • it wasn't very clear to me, I thought that your problem was the page reloading when you sent a message. Now I got it – Lucas Henrique Jan 31 '23 at 14:05
  • did you made sure that your frontend is connecting to the right address (in this case, your API running with socket.io)? Check the console to see if there aren't any errors connecting and maybe try to do a simpler function to receive the message, one that only logs the incoming message from the backend. This way you can make sure that you're connected to the right address – Lucas Henrique Jan 31 '23 at 14:08
  • the address can be use. i already implement everything based on code. however the problem is when sender send message the receiver need to reload page to get the latest message. the problem is how to make it automatically get the latest message withour reload the page? but at receiver page its already can be view at chat box that the latest message. can i know where's the code that i need to update or change based on code that i gave? – Wan Ilhami Jan 31 '23 at 19:57
  • Exactly, the problem seems to be a connection issue, your code is fine, I don't see anything wrong there. Test the connecion itself, see if your backend prints something when you connect to it and check for errors at the console (for frontend) and terminal (for your backend). – Lucas Henrique Feb 13 '23 at 20:38
0

You can write socker.write() method for accessing real time messages in nodejs.

Tyler2P
  • 2,324
  • 26
  • 22
  • 31
  • how to use it? can give an example using my file give? i tried to use socket.emit, socket.io and other, it still doenst work – Wan Ilhami Jan 31 '23 at 12:58