1

I've spent the night on trying to figure this out and have finally decided to give up and ask for help.

I'm building a web-app with AngularJS that is designed to work with flakey connections (mobiles).

I'm trying to implement the functionality for a user to add a object (whether that's an appointment, book, etc is irrelevant) to the server.

Service that handles syncing objects with the server:

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;
    }
  });

'app' service that the status bar is bound to:

'use strict';

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

Template binding to the 'app' service inSync property:

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

Specific object service that sends data from the controller to the syncUp service:

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() {});
      }

Everything is working as it should (data is being persisted to the server and the ID is being returned and replacing the tempId just fine. The problem is, when the inSync key on the 'app' service is updated, the class isn't added/removed from the div as it should be with ng-class in the template. If I load another route, that will force iterate through whatever internal cycle angular is doing and update the class on the template.

I've tried all manner of $apply() solutions, moving where the app.inSync key is set back to true, looping a function watching it. It's being set in all the right places (from debugging I know it's set back to true correctly), I just can't figure out how to make the change appear on the UI.

I tried: $rootScope.$apply(function() { app.inSync = true; });

Which gave me an error (already running a digest, or something).

So I tried the 'safeApply' version that has been circulated on many answers/blogs, which didn't throw the error, but didn't work either.

As far as I can figure out, the UI should be updated when promises are resolved (both the http and my syncUp.addObject promise are resolved, so I'm not sure why it's not working.

Any ideas? I need to keep the current implementation of promises to be able to set the returned ID from the server on the added object, to avoid a circular-dependency issue between the syncUp and object angular services.

Edit:

And the status bar directive:

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

2 回答 2

1

您在模板中所做的引用是指当前$scope. 服务通常不会在 中创建或添加任何内容$scope,因此将属性放在服务上不会使它们对模板可用。要在 上获取内容$scope,您需要使用控制器。您可以使用该ng-controller指令来引用控制器,您将在第一个 AngularJS 教程中找到这方面的示例。

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

这是好方法;您也可以通过将 inSync = true 放在原样上来摆脱它$rootScope

service('syncUp', function syncUp($http, $q, app, $rootScope) {
    // (...)
    $rootScope.inSync = true;
于 2014-01-22T21:49:20.883 回答
0

看起来您希望看到在服务(“应用程序”)和模板之间运行的绑定。很难判断我们是否没有看到整个画面。按照这个假设,您需要重构以便在控制器上设置绑定。

我希望控制器设置看起来像这样:

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

现在,您将在“inSync”属性上连接双向绑定。

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

如果我不在基地,请使用更多上下文更新您的问题,或者更好地解决问题。

于 2014-01-22T21:49:05.367 回答