Angular in conjunction with socket.io does not immediately show messages on screen

I am currently working on developing an instant messaging app (chat) using socket.io and Angular. I have two main files: index.html and index.js as shown below. The chat functionality is working well, but I am facing an issue where the messages do not appear immediately in the chat window when I press the "Send" button. Instead, I only see the message once I click inside the input text field with the mouse cursor. What could be causing this delay?

In addition, I am noticing that the <li> tag is being displayed as part of the text instead of being interpreted as an HTML tag. My goal is to have this tag properly rendered as HTML. How can I fix this issue?

Thank you.

index.html

<html>
<head>
  <title>My Chat</title>
  <link rel="stylesheet" type="text/css" href="css/style.css">
  <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
  <script src="/socket.io/socket.io.js"></script>
</head>
<body>
  <div ng-app="myApp" ng-controller="myCtrl">
    {{ message }}
    <form >
      <input autocomplete="off" ng-model="exampleText" type="text" />
      <button type='button' ng-click="submit()">
        Send
      </button>
    </form>
  </div>
  <script>

   var app=angular.module("myApp", []);
   var socket = io();
   app.controller("myCtrl", function($scope) {
     $scope.message='';
     $scope.submit=function(){
      socket.emit('chat message', angular.copy($scope.exampleText));
      $scope.exampleText='';
      return false; 
    }
    socket.on('chat message', function(msg){
      $scope.message=$scope.message+" <li> "+ msg;
    });
  });

</script>
</body>
</html> 

index.js

var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.use(express.static(__dirname + '/'));
app.get('/', function(req, res){
    res.sendFile(__dirname + '/index.html');
});

io.on('connection', function(socket){
    console.log('a user connected');

    socket.on('chat message', function(msg){
        io.emit('chat message', msg);
    });

    socket.on('disconnect', function(){
        console.log('user disconnected');
    });

});

http.listen(3000, function(){
    console.log('listening on *:3000');
});

Answer №1

To address the issue of message delay, take a look at the chat message handler code snippet below:

socket.on('chat message', function(msg){
  $scope.message=$scope.message+" <li> "+ msg;
});

The problem lies in the fact that the message update occurs outside of the scope digest loop. To resolve this, try the modified approach provided here:

socket.on('chat message', function(msg){
  $scope.$apply(function() {
     $scope.message=$scope.message+" <li> "+ msg + "</li>";
  });
});

Furthermore, if you wish to eliminate the display of "li" tags and directly show incoming messages, consider converting "message" into an array format. Update your HTML layout as follows:

{{ message }}

to

<ul>
    <li ng-repeat="message in messages">{{message}}</li>
</ul>

Subsequently, modify the controller by replacing:

$scope.message='';

with

$scope.messages = [];

Finally, adjust the chat message handler code to:

socket.on('chat message', function(msg){
    $scope.messages.push(msg);
});

By implementing these changes, you should be able to resolve the issue.

Answer №2

One issue you may encounter is when using socket.on from index.html outside of your angularjs app scope, which means it may not watch for method calls.

To prevent such issues, you can utilize $scope.$apply in the following way:

socket.on('chat message', function(msg) {
  $scope.$apply(function() {
     ...
  });
});

Alternatively, consider using angularjs component for socket.io, which is fully integrated with $scope and eliminates the need for additional method calls.

// within the main module of the application
angular.module('myApp', [
  'btford.socket-io',
  'myApp.MyCtrl'
]).
factory('mySocket', function (socketFactory) {
  return socketFactory();
}).
controller('MyCtrl', function (mySocket) {
  // ...
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The misleading A*(A-star) algorithm inaccurately produces faulty routes and ultimately collapses

I am currently working on implementing the A*(A-star) algorithm in react.js, but I am facing a problem. Whenever the startNode (green) or destinationNode (blue) have more than one neighbour or if there is a cycle in the graph, my program crashes. There see ...

Should You Ajaxify Your Website?

Absolutely loving the way Ajax can transform a web app into something that performs like a desktop application. The concern, however, arises when dealing with high volume sites. Currently working on an intranet-based database app meant for only 2-4 users a ...

Is it possible to show a pop-up window containing aggregated data when the jQuery double-click event

How can I create a pop-up window to display aggregated data when the Double-click event is triggered in jQuery? In my code, each questionId has multiple related reasons. When a user clicks or selects a questionId button/event, the selected questionId will ...

What is the purpose of using an img tag to retrieve a URL that is not an image?

Upon investigating a slow page load, I came across something interesting in the HTML: <img src="/ajax?action=askedAboutCookies" style="display:none" width="0" height="0" alt="" /> When the page loads, it sends a request but never receives a respons ...

Is there a way for me to convert my (TypeScript Definition) .d.ts file into a (JavaScript) .js file?

It seems that there are plenty of guides available on converting a file from .js to .d.ts, but not the other way around. Specifically, I have some code in .d.ts format and I would like to convert it into JavaScript. Can anyone offer assistance with this t ...

NPM is having trouble locating a shell script

An error is encountered when running npm run build: '.' is not recognized as an internal or external command, operable program or batch file. Here is the npm file that contains relevant scripts: "scripts": { "postinstall": "jspm instal ...

Node.js encountering issues with multiple concurrent connections to SQL servers in mssql due to interference between them

I am currently utilizing mssql in my Node.js express application to establish connections with multiple databases on various SQL servers. To illustrate the basic structure of my code, I have created the following example: app.get('/api/example') ...

Issue with NodeJS proxy not functioning correctly

The current request route starts at localhost:3001, passes through a proxy located on the same localhost at localhost:3001/proxy, where it is then directed to the Salesforce instance. The ExpressJS proxy and AngularJS client-side app are utilized for this ...

One can activate an event once all templates and data have been fully loaded

Is there a way to trigger an event once all templates and data have finished loading in an AngularJS application? I've completed my app, but on the production server there seems to be a delay where the templates load first and then the data follow, le ...

Route.get() is looking for a callback function, but instead received an [object Promise]

Currently, I am in the process of developing a REST API using express and following the architecture outlined in this particular article. Essentially, the setup involves a router that calls a controller. Let me provide you with an example of how a call is ...

In JQuery, an empty string will be returned if it contains the dollar sign character

In the scenario presented here, the value is retrieved accurately with the exception of when it includes a $ symbol at the beginning (e.g. $25.00), in which case it consistently results in an empty string. HTML: <input type="number" class="form-contro ...

Determine whether the elements in the master array match the elements in the child array

Checking for data presence in arrays: [ { "productDisplay": "ZXP 105", "productNumber": "WZDR 112" }, { "productDisplay": "ZXP 106", "productNumber": "WZDR 113" } ] ChildArray [{productDisplay:"ZXP 105", ...

Unable to continue due to being stuck in the "Starting packager" phase of React Native development

Whenever I attempt to start the React Native project (you can find it here), the npm start script gets stuck on Starting packager I have already checked these resources regarding the issue: react-community issue: 203 react-native-stuck-at-starting-packa ...

Ways to manage V-show in a dynamically changing environment

I am currently in the process of developing an Ecommerce shopping platform. I have been importing data from a JSON file and successfully printing it using a v-for loop. One feature I am implementing is the Show Order Details option, where clicking on it re ...

Tips for hiding the overflow scrollbar on Microsoft Chrome when there is no content to scroll

Looking for a solution to hide scroll bars in Microsoft Chrome, but only when there is no content to scroll? The current div and styles always show the horizontal and vertical scroll bars, even when the height exceeds the content. <div style="backgroun ...

Material UI: Dynamic font scaling based on screen size

If I were to adjust the font size responsively in Tailwind, here's how it would look: <div className="text-xl sm:text-4xl">Hello World</div> When working with Material UI, Typography is used for setting text sizes responsively. ...

I'm feeling completely lost trying to understand cors in conjunction with fetch, particularly when an options request is

I am using whatwg fetch in the code snippet below: const headers = new Headers(); //uncommenting this causes the preflight options request to be sent //headers.append('x-something', 'foo'); const response = await fetch(&apos ...

Convince me otherwise: Utilizing a Sinatra API paired with a comprehensive JS/HTML frontend

As I embark on the journey of designing a social website that needs to support a large number of users, I have come up with an interesting approach: Implementing Sinatra on the backend with a comprehensive REST API to handle all operations on the website ...

Find the specific element that is visible within a customized viewport, such as a div or ul

Exploring the capabilities of the Viewport Selectors for jQuery plugin, here is a snippet of its source code: (function($) { $.belowthefold = function(element, settings) { var fold = $(window).height() + $(window).scrollTop(); return fold <= $ ...

Unlock the potential of the Node.js gm library: a comprehensive guide on generating convert commands for layering multiple images in sequence

Can anyone help me with the equivalent nodejs gm library command for this imagemagick cli command? Here is the link to the gm library. Original ImageMagick CLI Command: convert -size 669x122 xc:none img1.jpg -geometry +223+0 -composite img2.jpg ...