AngularJS 1.2.0 を使用して、websocket を介して単純なメッセージング アプリを作成しています。HTML は、リストに対して ng-repeat を使用して、合計出力 (入力しているメッセージの配列) を生成しています。ファクトリを使用して「プライベート」データとメソッドをホストし、ビュー モデルと関数のみを公開してコントローラー内のデータを操作しています。
<form class="form-search">
<input type="text" ng-model="model.input" class="input-large"
placeholder="Enter your message:">
<button type="submit" class="btn" ng-click="sendMessage()">Send</button>
</form>
<ul>
<li ng-repeat="message in model.output track by $index" ng-bind="message"></li>
</ul>
application.controller('MessageCtrl', ['$scope', 'MessageService', function($scope, Service) {
$scope['model'] = Service.view;
$scope.sendMessage = function() {
Service.sendMessage();
};
$scope.$watchCollection(function() {
return Service['view'];
}, function(data) {
$scope['model'] = data;
});
}])
.factory('MessageService', function('Restangular') {
var Service = {
// other private properties
view: {
input: null,
output: []
}
};
openConnection();
function openConnection() {
// retrieves websocket URL over Restangular
// opens websocket
}
function sendMessage() {
// sends input over socket
// promises are resolved and unshifted onto Service['view']['output'].
}
return {
view: Service['view'],
sendMessage: function() {
sendMessage();
}
}
});
Service['view'] の出力配列が新しいメッセージを取得したときに DOM の ng-repeat が更新されないことを除いて、すべてが正常に機能しています。このスレッドのソリューションとして $watchCollection を使用してみました: AngularJS : The correct way of binding to a service propertiesですが、これも機能しません。DOM を再レンダリングする唯一の方法は、入力テキストを変更するか、CSS でホバー状態をトリガーして強制的に再レンダリングすることです。
この設定で、プロミスが新しいメッセージ データで解決され、出力配列にシフト解除されるとすぐに DOM がレンダリングされるように、ダイジェストをトリガーする最良の方法は何でしょうか? $rootScope を使用してイベントを発生させないようにしたいのは、他のコントローラーがファクトリを使用すると非常に汚れる可能性があるためです。