带有父控制器和多个子控制器的$ rootscope。$ broadcast和$ scope。$ on

时间:2016-04-04 08:03:15

标签: angularjs

在我的index.html文件中,我得到一个appController,就像main controller一样,必须在$ rootScope中加载一些基本设置,以便我可以在child controllers中使用这些设置(data-ui-view = ui-router插件)

<body ng-controller="appController">

    <div data-ui-view></div>

</body>

appController我使用服务(appService),我从数据库中获取数据并将一小部分数据放入$ rootScope属性formData

appService.formData()
.then(function(data) {
    $rootScope.formData = data[0].num;
    if ($rootScope.formData) {
        $rootScope.$broadcast('afterFormDataLoaded');
    }
}) 

在$ rootScope.formData填充实际数据之前,其他(子)控制器不运行非常重要。所以为了实现这一点,我在父控制器中使用$rootScope.$broadcast并且:

$scope.$on('afterFormDataLoaded', function () {
    // the code
})
子控制器中的

$scope.$on

这个有效!我的子控制器仅在主控制器中的$broadcast设置为afterFormDataLoaded后才会运行。

但是当我改变视图并且从一个孩子(视图和控制器)导航到另一个孩子时,我遇到了问题。 对我来说很明显我会遇到$broadcast方法的问题,因为当我加载/刷新页面而不是当我更改视图时,$ broadcast会运行一次。因此,当我更改视图时,不会触发$scope.$on

让我的所有子控制器等到我的父异步功能成功完成并且$ rootScope.formData是 true 的正确和最合理的方法是什么?

2 个答案:

答案 0 :(得分:1)

在ui-router中,您可以将resolve参数添加到状态声明(https://github.com/angular-ui/ui-router/wiki#resolve)。为了使它工作,你必须存储承诺的某个地方直到解决。

这里是一个例子

angular.run(['$rootScope', '$q', function($rootScope, $q){
    var defer = $q.defer();
   var dataPromise = defer.promise;
   $rootScope.resolveDataPromise = function(data){
       defer.resolve(data);
   } 
}]);

angular.config(['$stateProvider', function($stateProvider){
   $stateProvider.state({
       resolve:{
           myData:['$rootScope', function($rootScope){
              return $rootScope.dataPromise;
           }]
       }
   });
}]);

appService.formData().then(function(data) {
    if(data[0].num){
        $rootScope.resolveDataPromise(data[0].num);
    }
}) 

注意:要获取解析数据,只需将其注入控制器,解析对象的关键字就是名称: myData

你可以在你需要的所有状态下定义它,也可以在所有状态的父级中定义它,这将有效。

答案 1 :(得分:0)

你可以在相应的控制器上引用$ rootScope,如果$ rootScope.formData被填充,则在start函数中读取,如果没有注册你的监听器。

此外,如果您使用的是ui-router resolve,可能会完全按照您的意愿行事。