8

I'm trying to change my angular model after a websocket push from the server. How is it possible to change values like $scope.contacts each time the server serves new data..?

I'm not sure if it is possible by using $apply. I know that I can access the DOM element retrieve the scope and then change the values, but there should be a better solution!

I'm really interested in a solution to update the angular model from outside without creating angular modules since I'm using relative data sources that emit change events. Is there no simple way to do that like in Backbone.js where you can say:

var book = new Backbone.Model({ title: 'value' });
book.set("title", "A Scandal in Bohemia");

What I want in angularjs is something like:

function MyController($scope) {
    $scope.contacts = [];
}

datasource changed -> function () {
    MyController.set('contacts', 'value'); // change angular scope property
}
2
  • 2
    yes it is possible with $apply Commented Feb 5, 2013 at 8:36
  • @Jimbo Your answer is exactly what I'd already described in my question. I'm searching for an easier way, but I think writing my own factory module is the best solution. Commented Nov 20, 2013 at 12:32

3 Answers 3

11

Look at socket.io angular service:

angular.module('app')
  .factory('socket', ['$rootScope', function ($rootScope) {

    var socket = io.connect();

    return {
      on: function (eventName, callback) {
        socket.on(eventName, function () {  
          var args = arguments;
          $rootScope.$apply(function () {
            callback.apply(socket, args);
          });
        });
      },
      emit: function (eventName, data, callback) {
        socket.emit(eventName, data, function () {
          var args = arguments;
          $rootScope.$apply(function () {
            if (callback) {
              callback.apply(socket, args);
            }
          });
        })
      }
    };

  }]);

and controller using it:

angular.module('app')
  .controller('Controller', ['$scope', 'socket', function ($scope, socket) {

    socket.emit('register')

    socket.on('register', function (data) {
        $scope.data = data;
    });

}]);
Sign up to request clarification or add additional context in comments.

2 Comments

That's a really nice example but it will not work in my case, since I'm synchronizing data with Collections on the client and these Collections emit the change events. I can change to code to get it working with your suggestion, but what I really want to have is scope.contacts = db.collection('contacts').find('favorites'); and set the angular model property every time my collection is updated and then call this code.
Which db you are using on client? Does find() have callback function? Could you show full source of client?
2

just do it like below

 socket.onmessage = function (event) {
     scope.$apply(function(){
       // modify scope values here 
     }
    };

3 Comments

Correct me if I'm wrong but when I have retrieved my scope I can simply change values by scope.variable = 'value'. My question is about how to retrieve the scope I want to change on a simple way.
have u created a angular service for making websocket request
+1 Great find @Ajaybeniwal - I've combined your code above with the ability to retrieve the scope of an element within your own JS and put it in a new answer below :)
1

Well, the marked answer is certainly not a "simple way" as requested by OP. Here's a much simpler solution.

Retrieve the scope wherever you want in your own JavaScript code:

var scope = angular.element($("#elementID")).scope();

Change a value in your Angular $scope variable, but from your external JavaScript:

scope.$apply(function() {
    scope.yourArrayForExample.push({name: 'New, external value'});
});

Here's a JSFiddle.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.