【问题标题】:How to update $scope object without reload of page?如何在不重新加载页面的情况下更新 $scope 对象?
【发布时间】:2016-03-12 08:48:32
【问题描述】:

你好,

所以我从 Python 返回一个字典,然后在将它传递给 Angular 之前对其进行 jsonify 处理。

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

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

return jsonfiy(the_dict)

此字典包含状态、排除包列表和错误消息。

结果通过 dataFactory 函数返回给 Angular,如果状态为 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);
                 }
            }
        }

【问题讨论】:

  • 用户点击离开按钮后,您是否进行任何视图更改?
  • 还没有。一旦我可以立即更新值,我将使用 $scope.failedPkgs 显示一个显示 pkgs 失败的弹出框
  • 那我还没有完全理解这个问题。你能解释一下这部分问题吗..will only show the updated values AFTER you click back in the browser and then go back to the page
  • 道歉。我的意思是,如果您重新加载页面,您将通过控制台看到更新的 $scope.failedPkgs 值。这不是对 $scope.failedPkgs 的即时更新。
  • 您尝试在 if 语句内的 $http 帖子中添加 console.log(res.data.excludedPkgs) 以验证 $storage 中的值是否在发布时更新。如果这是更新,您可以编写更多代码来更新控制器 $scope 变量中的值 failedPkgs$storage. failedPkgs..

标签: javascript python angularjs dictionary


【解决方案1】:

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

AngularJS 为常见的原生 JS 异步行为提供了包装器:

事件 => ng-click
超时 => $timeout
jQuery.ajax() => $http

当您完成更新$scope 时,只需执行如下操作:
$scope.$apply()
ps:也适用于$rootscope

编辑:

在调用$scope.$apply()时防止错误$digest已经在进行中

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

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

如果$digest$apply 正在进行,$scope.$$phase 将返回“$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)
         }

        });
      }

【讨论】:

  • 这个问题是 $scope.$apply() 抛出 Error: [$rootScope:inprog] $digest already in progress
  • 你说在哪里打电话?在我的 onClick 函数中?
  • 每次认为需要更新$scope的变量时都可以调用。
  • 这里的问题是 $scope 没有注入到 dataFactory 中。控制器是可以访问 $scope 的对象。因此,当我运行您的更新时,我收到:ReferenceError: $scope is not defined
【解决方案2】:

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

$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 可能没有返回承诺。

【讨论】:

  • 唯一的问题是我收到:TypeError: Cannot read property 'then' of undefined
【解决方案3】:

你好,

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

数据工厂:

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

        });
      },

包控制器:

$scope.$on('failedPackages', function(event, args){
        console.log(event)
        console.log(args)
    });

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

【讨论】:

    猜你喜欢
    • 2010-12-22
    • 2021-07-17
    • 1970-01-01
    • 2014-04-12
    • 1970-01-01
    • 1970-01-01
    • 2020-04-20
    • 2014-05-13
    • 2017-03-03
    相关资源
    最近更新 更多