Reputation: 1818
I am trying to create instanse message app (chat) using socket.io and Angular. I have 2 files: index.html, and index.js showed below. the chat works fine expect that when I press on the "Send" button I don't see the message stright away in the chat window. I only see the message once I press the input text field with the mouse cursor... What Am I doing wrong?
i addition, I also see the tag < li > as part of the text. I want this tag to be an html tag, not a text string...
Thanks
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');
});
Upvotes: 2
Views: 1478
Reputation: 5055
Problem is that you are using socket.on
from index.html
that is outside of your angularjs app scope and it does not watch that method calls.
To avoid problems like that you can use $scope.$apply
like this
socket.on('chat message', function(msg) {
$scope.$apply(function() {
...
}
});
Or better use angularjs component for socket.io that is completely attached to $scope
and you don't to call additional methods
// in the top-level module of the app
angular.module('myApp', [
'btford.socket-io',
'myApp.MyCtrl'
]).
factory('mySocket', function (socketFactory) {
return socketFactory();
}).
controller('MyCtrl', function (mySocket) {
// ...
});
Upvotes: 0
Reputation: 1623
First, the message delay. Look at the chat message handler:
socket.on('chat message', function(msg){
$scope.message=$scope.message+" <li> "+ msg;
});
- the problem here is that message update happens outside of the scope digest loop. Try the following:
socket.on('chat message', function(msg){
$scope.$apply(function() {
$scope.message=$scope.message+" <li> "+ msg + "</li>";
});
});
Next, if you want to get rid of "li" tags showing, you need to stop constructing HTML in your controller and display incoming messages directly. This can be achieved by making "message" an array of messages. In your HTML layout, replace:
{{ message }}
with
<ul>
<li ng-repeat="message in messages">{{message}}</li>
</ul>
then replace, in the controller
$scope.message='';
with
$scope.messages = [];
and finally change the chat message handler to:
socket.on('chat message', function(msg){
$scope.messages.push(msg);
});
This will do the trick.
Upvotes: 7