Angular App:如何同步多个视图的调用

时间:2015-10-06 06:38:04

标签: javascript angularjs angular-ui-router

我正在构建一个有角度的单页应用程序,它具有这样的结构。

"app.parent - parent state"
"app.parent.childState - child state"
"app.parent.childSatate" has 4 multiple named view inside it.

一旦所有4个视图都获取了各自的数据,我必须在父级上显示一些内容。 有什么建议吗?

注意:如果解决方案是纯粹独立的,它可以帮助我很多,如果我删除/添加任何控制器,那么我不需要一直对父进行更改。

3 个答案:

答案 0 :(得分:1)

假设您有4个服务,您知道这些服务将成为4个不同子视图的数据源。您可以设置服务以便它们返回引用,但仍然可以访问基础承诺。这个想法是你希望你的视图在渲染视图时使用引用;父母将使用$ q.all等待各个承诺在显示之前得到解决。

<强>工厂

app.factory('service1', function($http) {
    var data1 = [];
    return {
        promise: $http({...}).success(function(result) {
                     angular.copy(result, data1);
                 }),
        getData: function() {
            return data1;
        }
    }
}); 

app.factory('service2', function($http) {
    var data2 = [];
    return {
        promise: $http({...}).success(function(result) {
                     angular.copy(result, data2);
                 }),
        getData: function() {
            return data2;
        }
    }
}); 
app.factory('service3', function($http) {
    var data3 = [];
    return {
        promise: $http({...}).success(function(result) {
                     angular.copy(result, data3);
                 }),
        getData: function() {
            return data3;
        }
    }
}); 

app.factory('service4', function($http) {
    var data4 = [];
    return {
        promise: $http({...}).success(function(result) {
                     angular.copy(result, data1);
                 }),
        getData: function() {
            return data4;
        }
    }
}); 

儿童控制器

app.controller('ctrl1', function($scope, service1) {
      $scope.data1 = service1.getData();
});
app.controller('ctrl2', function($scope, service2) {
      $scope.data2 = service2.getData();
});
app.controller('ctrl3', function($scope, service3) {
      $scope.data3 = service3.getData();
});
app.controller('ctrl4', function($scope, service4) {
      $scope.data4 = service4.getData();
});

家长控制器

app.controller('parent', function($scope, $q, service1, service2, service3, service4) {
     $q.all(
       [service1.promise,
        service2.promise,
        service3.promise,
        service4.promise])
      .then(function() {
           $scope.done = true;
      });
});

家长视图

 <div ng-show="done"> All child data loaded </div>

更模块化的方法

如原始帖子中所述 - 如果父控制器不必依赖于各个数据源的注入,那将是很好的。这样,当子项更改数据源(添加源或删除源)时,父控制器不会受到影响。

这可以通过依赖指令到指令的通信来完成。我们的想法是子指令可以使用父指令注册其数据源。一旦注册了所有数据源,父指令就可以使用$ q.all,如第一个示例所示。

家长指令

app.directive('parent', function($q) {
     return {
         restrict: 'A',
         require: 'parent',
         controller: function($scope) {
              $scope.done = false;
              var promises = [];
              this.register = function(promise) {
                  promises.push(promise);
              }
              this.getPromises = function() {
                  return promises;
              }
         },
         link: function(scope, element, attr, parent) {
              $q.all(parent.getPromises())
                  .then(function() {
                      scope.done = true;
                  });
         }
     }
});

儿童指令

app.directive('child', function(service1) {
     return {
         restrict: 'A',
         require: '^parent',
         controller: function($scope) {
             $scope.data1 = service1.getData();
         },
         link: function(scope, element, attr, parent) {
             parent.register(service1.promise);
         }
     }
});

<强> HTML

<div parent>
     <div child>
          <div> {{data1}} </div>
     </div>
</div>

又一种方法

您可能已经注意到,虽然第二种方法不会影响父控制器,但子控制器依赖于父指令。我们如何从子控制器中消除这种视图依赖?

使用服务。创建一个允许子控制器注册其承诺的父服务;并且还从父服务公开一个方法,该方法返回一个在所有子promise都已解析时解析的promise。

当您为整个页面设置单点加载时,这可能是首选方法。

家长服务

app.factory('parentService', function($q) {
     var promises = [];
     return  {
         promise: function() {
             return $q.all(promises);
         },
         register: function(promise) {
             promises.push(promise);
         }
     }
});

儿童控制器

app.controller('childCtrl1', function(parentService, service1) {
     parentService.register(service1.promise);
});

app.controller('childCtrl2', function(parentService, service2) {
     parentService.register(service2.promise);
});

家长指令

app.directive('parent', function(parentService) {
      return {
          restrict: 'A',
          controller: function($scope) {
              $scope.done = false;
          },
          link: function(scope) {
              parentService.promise().then(function() {
                  scope.done = true;
              });
          }
      }
});

<强> HTML

<div parent>
    <div ng-show="done">All child data loaded</div>
    <div ng-controller="childCtrl1">
         {{ data1 }}
    </div>
    <div ng-controller="childCtrl2">
         {{ data2 }}
    </div>
</div>

答案 1 :(得分:0)

在所有四个控制器中使用$ rootScope(推荐的工厂/服务)(对于所有4个视图),并且具有一定的计数/标志,用于跟踪所有控制器和主页面/控制器上的数据获取检查$ rootScope / factory值。

$ rootScope / facetory / services可通过控制器/视图访问,因此您可以在多个控制器中进行修改并访问其他控制器/工厂/服务上的最新值。

相关文件: https://docs.angularjs.org/api/ng/service/ $ rootScope https://docs.angularjs.org/guide/services

答案 2 :(得分:0)

Create a service or factory and inject it into the controllers you need it in, that way you will not have to repeat code.

You can also use this method to share data across your app by making variables avalible via dependency injection.