2012-04-16 20 views
55

La actualización de la propiedad del modelo no tiene ningún efecto en la vista al actualizar el modelo en la devolución de llamada de evento, ¿alguna idea para solucionar esto?La vista no se actualiza en AngularJS

Este es mi servicio: se añadió

angular.service('Channel', function() {   
    var channel = null; 

    return {   
     init: function(channelId, clientId) { 
      var that = this;   

      channel = new goog.appengine.Channel(channelId); 
      var socket = channel.open(); 

      socket.onmessage = function(msg) { 
       var args = eval(msg.data);    
       that.publish(args[0], args[1]); 
      }; 
     }  
    }; 
}); 

publish() función dinámicamente en el controlador.

controlador:

App.Controllers.ParticipantsController = function($xhr, $channel) { 
    var self = this; 

    self.participants = [];  

    // here publish function is added to service 
    mediator.installTo($channel); 

    // subscribe was also added with publish   
    $channel.subscribe('+p', function(name) { 
     self.add(name);  
    });     

    self.add = function(name) {  
     self.participants.push({ name: name });  
    } 
}; 

App.Controllers.ParticipantsController.$inject = ['$xhr', 'Channel']; 

Vista:

<div ng:controller="App.Controllers.ParticipantsController">  
    <ul> 
     <li ng:repeat="participant in participants"><label ng:bind="participant.name"></label></li> 
    </ul> 

    <button ng:click="add('test')">add</button> 
</div> 

Así que el problema es que al hacer clic en el botón actualiza la vista correctamente, pero cuando llegue el mensaje de los nadas Canal sucede, incluso el add() la función se llama

Respuesta

126

Te has perdido $scope.$apply().

Cuando toque cualquier cosa desde fuera del mundo angular, debe llamar al $apply para notificar a Angular. Eso podría ser de:

  • devolución de llamada xhr (manejado por el servicio $ http)
  • setTimeout de devolución de llamada (manejado por $defer servicio)
  • devolución de llamada
  • DOM Evento (manejado por directivas)

En su caso, haga algo como esto:

// inject $rootScope and do $apply on it 
angular.service('Channel', function($rootScope) { 
    // ... 
    return { 
    init: function(channelId, clientId) { 
     // ... 
     socket.onmessage = function(msg) { 
     $rootScope.$apply(function() { 
      that.publish(args[0], args[1]); 
     }); 
     }; 
    } 
    }; 
}); 
+1

Esto fue útil, y una vez pensé acerca de por qué Para hacer esto en el caso de los eventos DOM/jQuery, tenía sentido para mí y pude aceptarlo. – duma

+0

Cool. No sabía que podrías inyectar el alcance de la raíz. – heneryville

+4

Para las devoluciones de llamadas 'setTimeout', use el servicio' $ timeout' en su lugar: https://coderwall.com/p/udpmtq – itghisi

Cuestiones relacionadas