2014-01-22 103 views
1

我花了整晚的时间试图弄清楚这件事,最后决定放弃并寻求帮助。Angularjs UI不会更新由承诺更新的服务绑定?

我正在构建一个带有AngularJS的Web应用程序,该应用程序可以与Flakey连接(手机)一起工作。

我试图为用户添加一个对象(无论是约会,书籍等是不相关的)到服务器的功能。与服务器处理同步对象

服务:

angular.module('App') 
    .service('syncUp', function syncUp($http, $q, app) { 

    this.addObject = function addObject(object) { 
     var deferred = $q.defer(); 
     app.inSync = false; 

     var httpConfig = { 
     method: 'POST', 
     url: 'http://myurl.dev/app_dev.php/api/add-object', 
     data: object 
     } 

     function persist() { setTimeout(function() { 
      $http(httpConfig). 
       success(function(data, status) { 
        app.inSync = true; 
        deferred.resolve(data.id); 
       }). 
       error(function(data, status) { 
        app.inSync = false; 
        persist(); 
       }); 
     }, 3000); 
     }; 

     persist(); 

     return deferred.promise; 
    } 
    }); 

状态栏势必'应用' 服务:

'use strict'; 

angular.module('App') 
    .service('app', function app($http, $q) { 
    this.inSync = true; 
    }); 

模板绑定到“应用程序'service inSync property:

<div class="status" ng-class="{'insync':inSync}"></div> 

从控制器将数据发送到syncUp服务特定对象服务:

this.addBook = function(book) 
     { 
     var tempId = syncUp.generateUid(); 
     this.books[tempId] = book; 
     this.books[tempId].tempId = tempId; 
     syncUp.addObject({ 
      'type': 'book', 
      'data': this.books[tempId] 
     }).then(function(newId) { 
      booksRef[newId] = book; 
      delete booksRef[tempId]; 
      }, function() {}); 
     } 

一切工作,因为它应该(数据被保存到所述服务器和被返回和更换的ID tempId就好了。问题是,当'app'服务上的inSync键被更新时,类不会被添加/从div中移除,因为它应该与模板中的ng-class一起使用。如果我加载另一条路线,那么将强制迭代角度正在执行的任何内部循环,并更新模板上的类。

我尝试过所有$ apply()方法,移动app.inSync键设置回true,循环一个函数观看它。它被设置在所有正确的地方(从调试我知道它被设置回true),我只是不知道如何使更改显示在用户界面上。

我试过了: $ rootScope。$ apply(function(){ app.inSync = true; });

这给了我一个错误(已经运行一个摘要,或其他)。

因此,我尝试了许多答案/博客上散布的'safeApply'版本,它没有抛出错误,但也没有工作。

至于我可以计算出,当承诺被解决(HTTP和我syncUp.addObject承诺得到解决出现的用户界面更新,所以我不知道为什么它不工作。

任何想法?我需要保持promise的当前实现能够在添加的对象上设置来自服务器的返回ID,以避免syncUp和对象角度服务之间的循环依赖问题。

编辑:

,状态栏指令:

angular.module('App') 
    .directive('navigation', function (app) { 
    return { 
     templateUrl: '/app/views/navigation.html', 
     restrict: 'E', 
     link: function (scope, element, attrs) { 
      scope.inSync = app.inSync; 
     } 
    } 
    }); 

回答

1

您在模板中所做的参考是指当前$scope上的对象。服务通常不会为$scope创建或添加任何内容,因此将属性放在服务上不会使它们对模板可用。要获取$scope上的内容,您需要使用控制器。您可以使用ng-controller指令来引用控制器,您会在the first AngularJS tutorials中找到此示例。

你应该做的是创建一个控制器并让它监听来自服务的事件。 Here's an example如何做到这一点。

这是不错的方法;您也可以通过在$rootScope上放置inSync = true来避开它;

service('syncUp', function syncUp($http, $q, app, $rootScope) { 
    // (...) 
    $rootScope.inSync = true; 
+0

对不起,我只是试图简化/提取相关代码的问题 - 应用程序被称为不同的东西,所以我不认为有任何命名冲突。我尝试将inSync变量添加到rootcope,但具有相同的问题 - 只有在保持新对象后更改路由时才更新。 – Anonymous

+0

我希望当你试图将它添加到根作用域时,你做了'$ rootScope.inSync = true'而不是'$ rootScope。$ apply(function(){app.inSync = true;});'as you你在问题中说过,对吧? – Philipp

+1

是的,但它不适用于我...但是,我只是尝试通过事件触发更改,并在指令中听取它......并且它工作正常!非常感谢。我很高兴这是排序......最好去我的终端道歉我把我的git日志中的淫秽。 :-) – Anonymous

0

它看起来像你希望看到的绑定服务(“应用”)和模板之间运行。很难说我们是否看不到整个图片。按照这个假设,您需要重构,以便在控制器上设置绑定。

我期望控制器设置看起来是这样的:

angular.module('App') 
.controller('app', function app($http, $q, $scope) { 
    $scope.inSync = true; 
}); 

现在,你会对“INSYNC”属性双向绑定钩取。

否则,您的模板看起来不错。

如果我离开的基地,请更新您的问题更多的上下文,或者更好,但一个小提琴煮沸问题。

+0

我使用将模板范围挂钩到app.inSync值的指令更新了问题。就我所能想到的而言,这应该足以把价值挂钩? – Anonymous