如何在不重新加载页面的情况下更新$ scope对象?

时间:2015-12-07 16:49:27

标签: javascript python angularjs dictionary

Howdie do,

所以我从Python返回一个字典,然后在将它传递给angular之前进行jsonify' ed。

例如,这是我从Python中返回的字典:

the_dict = {"success": False, excludedPkgs: ['12345', '45678'], message:'Failed to depart pkgs'}

return jsonfiy(the_dict)

此词典包含状态,已排除包的列表和错误消息。

结果通过dataFactory函数返回角度,如果状态为False则更新$ sessionStorage

departedFromPackages: function(ids, user_id){
        $http({
          method: 'POST',
          url: urlBase + 'depart/pkg/',
          data: {'order_id': ids, 'user': user_id}
        }).then(function(res){
         if (res.data.success == false) {
            $storage.failedPkgs = res.data.excludedPkgs;
         }

        });
      }

现在在我的Packages控制器中,我自动获取$ storage.failedPkgs并设置$ scope。$ watchCollection,我希望它会自动在控制台中显示更新的值:

包控制器

$scope.failedPkgs = dataFactory.getFailedPkgs();

    $scope.$watchCollection('failedPkgs', function (newVal, oldVal){
        console.log(newVal, oldVal)
    });

现在,问题是控制台最初在加载packages.html屏幕时显示未定义,这是有道理的。用户必须单击一个离开的按钮,该按钮将尝试离开包,这基本上意味着获取包信息并将其注入数据库表。

但是,如果您尝试离开已经离开的软件包,SQLAlchemy将返回完整性错误,因为您可以将重复的订单放入数据库中。

当上面的字典返回时显示False状态和失败的包列表。

我说所有这些都说,$ scope.failedPkgs只会在您重新加载屏幕后显示更新的值。

所以我的问题是,如何在不必重新加载页面的情况下立即更新$ scope.failedPkgs?或者你必须每次都重装吗?

****更新****

当我在POST请求中控制res.data.excludedPkgs时,它会立即显示更新的值,但控制器看不到重新加载的值:

departedFromPackages: function(ids, user_id){
        $http({
          method: 'POST',
          url: urlBase + 'depart/pkg/',
          data: {'order_id': ids, 'user': user_id}
        }).then(function(res){
         if (res.data.success == false) {
            console.log(res.data.excludedPkgs)
            $storage.failedPkgs = res.data.excludedPkgs;
            console.log($storage.failedPkgs)
         }

        });
      }

[1222822, 1222826, 1222819]

****更新****

这是返回$ storage.failedPkgs

的函数
getFailedPkgs: function(){
        return $storage.failedPkgs;
      },

****更新****

这是通过离开按钮的onClick事件调用的函数:

$scope.departed = function() {
            var selectedRows = [];
            $('.select-row-cb').each(function(){
                if ($(this).is(':checked')) {
                    selectedRows.push($(this).val());
                }
            });

            if (selectedRows.length > 0) {
                showProgressDialogueBox('Departing Package');
                if (selectedRows.length == $scope.dataTable.data().length) {
                    // All packages in wave are selected; Generate the entire wave
                    $scope.allPkgDeparted = 1
                    dataFactory.departedFromWaves($scope.waveid, $scope.user);
                } else {
                    dataFactory.departedFromPackages(selectedRows, $scope.user);
                 }
            }
        }

3 个答案:

答案 0 :(得分:0)

我认为你正在寻找这个: reference

  

AngularJS为常见的本机JS异步行为提供包装器:

     

活动=> ng-click
  超时=> $ timeout
jQuery.ajax()=> $ HTTP

在完成$scope.$apply()更新后执行如下:
$scope
ps:也适用于$rootscope

修改

在调用$digest

时,防止错误$scope.$apply()正在进行中

您可以通过选中$digest来检查$scope.$$phase是否正在进行中。

if(!$scope.$$phase) {
  //$digest or $apply
}

$scope.$$phase将返回" $ digest"或" $ apply"如果$digest$apply正在进行中。

  • $$phase对于框架是私有的,并且有充分的理由。
  • $scope.$apply(callback)调用$rootScope.$digest,这意味着它将重新删除应用程序及其所有子项的根范围,即使您处于隔离状态范围。

  • $scope.$digest()只会将其模型与视图同步,但不会消化其父级范围,这可以在处理具有独立范围的HTML的孤立部分时节省大量性能(来自主要是指令)。 $digest不接受回调:您执行代码,然后执行摘要。

修改 每次更新$scope或变量时都可以调用它:

departedFromPackages: function(ids, user_id){
        $http({
          method: 'POST',
          url: urlBase + 'depart/pkg/',
          data: {'order_id': ids, 'user': user_id}
        }).then(function(res){
         if (res.data.success == false) {
            console.log(res.data.excludedPkgs)
            $storage.failedPkgs = res.data.excludedPkgs;
          // ===========>
            if(!$scope.$$phase) {
              //$digest or $apply 
            }
         //<========
            console.log($storage.failedPkgs)
         }

        });
      }

答案 1 :(得分:0)

请检查以下模式是否解决了您的问题。

$scope.failedPkgs = dataFactory.getFailedPkgs();  // Initial call

$scope.buttonListener = buttonListener;

function buttonListener(){      // Executed on button click

    dataFactory.departedFromPackages().then(function(){
        $scope.failedPkgs = dataFactory.getFailedPkgs();
    });
}

在相同的按钮侦听器函数本身中,我们调用POST后更新$scope.failedPkgs的方法。这样您就不必再次单击该按钮。您可能必须将代码放在then块中,因为POST的工厂调用会返回一个承诺并且当前没有解决,因此如果您立即调用getFailedPkgs(),则不会有任何值在$storage.failedPkgs中,因为$ http可能没有返回承诺。

答案 2 :(得分:0)

Howdie do,

所以我决定从不同的角度来看待这个问题。我没有使用dataFactory.getFailedPkgs(),而只是通过rootScope发出广播并在我的控制器中发出它:

的DataFactory:

PowerMockito.spy(new SomeMod())

包控制器:

departedFromPackages: function(ids, user_id){
        $http({
          method: 'POST',
          url: urlBase + 'depart/pkg/',
          data: {'order_id': ids, 'user': user_id}
        }).then(function(res){
         if (res.data.success == false) {
            $rootScope.$broadcast('failedPackages', {packages: res.data.excludedPkgs});
         }

        });
      },

这使我可以立即查看失败的包。谢谢大家的帮助