【问题标题】:AngularJS directive with $http requests (inprog error)带有 $http 请求的 AngularJS 指令(inprog 错误)
【发布时间】:2014-01-03 04:53:21
【问题描述】:

我为此搜索并尝试了很多东西,我想我可能只是做错了。

我有一个单页应用程序,它具有非常相似的 DOM 片段,仅通过从服务提供给它们的数据来区分。每个 DOM 片段都有不同的 Web 服务。

我的 HTML 看起来像这样

<div section="foo">
    <ul>
        <li ng-repeat="item in collection">{{item.name}}</li>
    </ul>
</div>
<div section="bar">
    <ul>
        <li ng-repeat="item in collection">{{item.cost}}</li>
    </ul>
</div>

在我的真实示例中差异更加显着,所以不,我不能只是将“成本”更改为“名称”并让它们相同。

我有一个如下所示的指令:

angular.module("App").directive("section", ["BaseProvider", function(provider) {
    return {
        restrict: "A",
        scope: {},
        link: function($scope, element, attrs) {
            provider.query(attrs.section).success(function(response) {
                $scope.collection = response; // ** pay attention to this line **
            });
        }
    };
}]);

所以,它调用BaseProvider的查询方法,传入DOM元素的section属性。所以,在我的例子中是“foo”或“bar”。

BaseProvider 看起来像这样:

angular.module("App").factory("BaseProvider", ["$http", function($http) {
    var urls = {
        foo: "/something/foo.v1.json",
        bar: "/something/bar.v2.json"
    };

    return {
        query: function(base) {
            return $http.get(urls[base]);
        }
    };
}]);

这一切都有效。我遇到的是典型的指令问题 - 它没有及时处理$apply/$digest 循环,所以当我在指令内部执行$scope.collection = response 时,集合已设置,但DOM 不更新。

所以,我尝试运行 $scope.$apply(),但随后遇到 $digest in progress 错误。

http://docs.angularjs.org/error/$rootScope:inprog?p0=$digest

我已经尝试了这些建议,但仍然遇到问题。在这一点上我没有想法,也许我希望有一个可重用的指令和一个驱动整个事情的单一提供者不是要走的路。

我使用 FooCtrl 和 BarCtrl 完成了这一切,但我重复了很多次,感觉不对。

【问题讨论】:

  • 你能澄清一下你在这里真正想要完成的事情吗?你想共享 dom 但绑定到不同的数据和数据的不同属性?有两个部分还是两个以上?
  • 另外,我可能是错的,但我不认为指令是实现这一目标的最佳方式。嵌套控制器可能是更好的选择。
  • 嵌套控制器可能会更好。我正在寻找一种方法来避免与多个指令相关的进展问题,每个指令都执行 $http GET 和 $scope.$apply 以更新 DOM。
  • 两个以上的部分。

标签: javascript angularjs angularjs-directive angular-http


【解决方案1】:

如果您使用 angular 1.2.x 或更高版本,您的指令将无法工作,因为它使用的是隔离范围。隔离作用域意味着您分配给作用域的任何变量只能在作用域的内部模板中使用(即在指令中使用template: 属性定义的模板。

由于你的指令没有模板,你不应该使用隔离范围。而不是这样做:

scope: {}

你应该这样做:

scope: true

这将使指令创建一个范围但不隔离它。这将使您的指令的范围可用于外部模板(即您的 ng-repeat)。

请记住这一点,如果您没有在指令中定义模板,则几乎不应该使用隔离范围。

【讨论】:

  • 很高兴知道这一点。这将解决与执行 $http GET 并尝试使用 $scope.$apply 更新 dom 的多个指令相关的进展问题吗?如果我理解正确,那么执行 scope: true 会将其推送到控制器使用的沙箱类型的范围内,这将解决运行在自身中的摘要,因为我不需要手动执行 scope.apply - 它会更新范围按照预期的方式,一切都会回到原位。
  • 这绝对修复了它。我讨厌离得这么近而只是看不到它。非常感谢。
  • 您不应该在 $htpp.GET 上使用 $scope.$apply()。 $http 服务是一个角度服务,因此它已经意识到它应该执行一个摘要循环。除非您绑定到浏览器 dom 事件,否则很少需要使用 $apply(),在这种情况下,您需要将代码包装在 $apply() 中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-29
  • 2021-04-15
  • 2017-09-12
相关资源
最近更新 更多