【问题标题】:Scope variable are not available in the template范围变量在模板中不可用
【发布时间】:2016-04-29 01:43:50
【问题描述】:

我用 angular-seed 开始了一个项目。我将它与另一个具有 jQuery 的项目混合在一起。我无法访问模板中的范围变量。

JS:

'use strict';

angular.module('myApp.view1', ['ngRoute'])

.config(['$routeProvider', function($routeProvider) {
  $routeProvider.when('/view1', {
    templateUrl: 'view1/view1.html',
    controller: 'View1Ctrl'
  });
}])

.controller('View1Ctrl', ['$scope', function ($scope) {

    $scope.showView = true;
    $scope.proBlock = false;
    $scope.modelBlock = false;

    $.when(dbReadyDeferred).then(function() {
        $scope.proBlock = true;
        console.log('dbReadyDeferred.state()',dbReadyDeferred.state());
    });
...

HTML:

<div ng-show="showView">
    {{proBlock}}
</div>

在浏览器中显示:false。我的代码有问题吗?

谢谢

【问题讨论】:

  • 直接显示是假的还是div本身不显示?

标签: angularjs scope


【解决方案1】:

如果您确定您的函数 $.when(dbReadyDeferred).then(function() {}) 正在被调用,请更改您的控制器代码,如下所示:

.controller('View1Ctrl', ['$scope', '$timeout', function ($scope, $timeout) {

    $scope.showView = true;
    $scope.proBlock = false;
    $scope.modelBlock = false;

    $.when(dbReadyDeferred).then(function() {
        $timeout(function() {
             $scope.proBlock = true;
             console.log('dbReadyDeferred.state()',dbReadyDeferred.state());
        });
    });
}]);

由于您正在使用 jQuery 更改 $scope.proBlock 值,因此 Angular 不知道此更改,我们需要明确告诉 Angular 运行摘要循环。

我们也可以使用$scope.$apply(),但是将调用封装到$timeout 函数中是一种更简洁的方法。

阅读更多:AngularJS with Ajax Form submission needing to click twice

更新:

你可以像这样修改你的解析变量:

.config(['$routeProvider', function($routeProvider) {
  $routeProvider.when('/view1', {
    templateUrl: 'view1/view1.html',
    controller: 'View1Ctrl'.
    resolve: {
         dbState: ['$rootScope', '$q', function($rootScope, $q) {
               var promise = $q.when(dbReadyDeferred)

               promise.then(function() {
                   $rootScope.$broadcast("dbStateReady");
               });
               return promise;
         }]
    }
  });
}])

.controller('View1Ctrl', ['$scope', function ($scope) {

    $scope.showView = true;
    $scope.proBlock = false;
    $scope.modelBlock = false;

    var deregisterFunction = $scope.$on("dbStateReady", function() {
        $scope.proBlock = true;
        console.log('dbReadyDeferred.state()',dbReadyDeferred.state());
        deregisterFunction();   // Remove this watch for $on listener
    });
});

基本上,我们将$q.when(如提到的@shushanthp)移动到resolve,并使用$broadcast 了解数据库状态何时准备好使用$on

【讨论】:

  • 好的,非常感谢。有没有办法让这个更干净,并将延迟变量传递给 $routeProvider 的 resolve 属性?我在这里发布了一个问题:stackoverflow.com/questions/34943845/…
  • 谢谢。但是我看不到监视广播事件“dbStateReady”的意义,因为控制器的代码只会被执行一次 dbReadyDeferred 已解决,对吗?所以dbStateReady 必然会触发控制器的代码开始执行,不是吗?
  • 你是绝对正确的。您应该密切关注提高代码的性能。我已经更新了答案。
  • 非常感谢您的帮助!
【解决方案2】:

当你使用$.when 时,你必须明确地使用$timeout$scope.$digest

您可以使用 Angular 的 promise 库,它是 $q.when 方法,因为 AngularJS 会将手表附加到它并相应地更改。

 $q.when(dbReadyDeferred).then(function() {
      $scope.proBlock = true;
      console.log('dbReadyDeferred.state()',dbReadyDeferred.state());
 });

如果你想使用jQuery.when方法,那么使用$timeout如下:

$.when(dbReadyDeferred).then(function() {
     $timeout(function() {
         $scope.proBlock = true;
        console.log('dbReadyDeferred.state()',dbReadyDeferred.state());
       },0,false) // false it doesnt invoke digest again which helps in performance

    });

【讨论】:

  • 好的,非常感谢,$q.when 效果很好。你如何将这个传递给路由提供者的resolve
猜你喜欢
  • 1970-01-01
  • 2014-06-27
  • 2016-11-25
  • 1970-01-01
  • 1970-01-01
  • 2017-03-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多