AngularJS:ng-repeat 没有检测到范围的变化

Posted

技术标签:

【中文标题】AngularJS:ng-repeat 没有检测到范围的变化【英文标题】:AngularJS : ng-repeat doesn't detect changes in scope 【发布时间】:2014-02-17 15:17:40 【问题描述】:

我一直在阅读各种帖子、问题、答案和文档,但到目前为止还没有解决我的问题。

我正在使用 mbExtruder jQuery 插件,为了将它集成到 Angular 中,我为它创建了一个指令:

directive('mbExtruder', function($compile) 
            return 
                restrict : 'A',
                link : function(scope, element, attrs) 
                    var mbExtruderConfigurationAttrs = scope.$eval(attrs.mbExtruder);
                    mbExtruderConfigurationAttrs.onExtContentLoad = function() 
                        var templateElement = angular.element(angular.element(element.children()[0]).children()[0]);
                        var clonedElement = $compile(templateElement)(scope);                       
                        scope.$apply();
                        var contentElement = angular.element(angular.element(angular.element(element.children()[0]).children()[0]).children()[0]);
                        contentElement.replaceWith(clonedElement.html());
                    ;
                    element.buildMbExtruder(mbExtruderConfigurationAttrs);
                    $.fn.changeLabel = function(text) 
                        $(this).find(".flapLabel").html(text);
                        $(this).find(".flapLabel").mbFlipText();
                    ;

我正在提取容器 div、编译它、应用范围并用转换后的 div 替换原始 div。

现在,我正在使用 mbExtruder 的功能从单独的 HTML 文件中加载内容,如下所示:

<div>
<ul>    
    <li ng-repeat="property in properties">
        <span><img ng-src="../app/img/property.attributes['leadimage']"/></span>
        <a ng-click="openDetails(property)">property.attributtes['summary']</a>
    </li>
    <div ng-hide="properties.length">No data</div>
</ul>
</div>

并且,在视图的 HTML 中,我有以下内容:

<div id="extruderRight"
        mb-extruder="position: 'right', width: 300, positionFixed: false, extruderOpacity: .8, textOrientation: 'tb'"
        class="title:'Lista', url:'partials/listGrid.html'">
    </div>

我在指令中得到的范围是实际处理属性数组的父控制器的范围。 问题是,如果属性列表预先填充了一些数据,那么最终会出现在编译后的 HTML 中——很酷。但是,对属性的任何更改实际上都无济于事。我已经在指令中的属性上添加了监视处理程序,实际上,只要对属性进行任何更改,就会触发该处理程序,但是 ng-repeat 不会选择它。最初的想法是在开始时让属性列表为空 - 这导致 ng-repeat compile 仅具有以下输出:

<!-- ngRepeat: property in properties -->

这样做有问题吗?事实上,ng-repeat 声明实际上已经从 DOM 中消失了。

我在这里遗漏了一些明显的东西吗?我已经阅读了关于 $compile 和 ng-repeat 的文档,我想说我不需要自己操作 DOM,ng-repeat 应该可以完成它的工作。还是我完全错了?

谢谢。

编辑:Plunker

【问题讨论】:

你能创建一个 plunker 吗? 如果ng-repeat 注释出现时没有任何内容,这意味着properties 必须为空(或不可迭代)。如果没有完整的示例,很难诊断,但听起来可能存在更新指令范围而不是父控制器范围的问题。一个很好的调试工具是AngularJS Batarang。启用后,您可以检查每个元素的范围。这可以让您看到properties 的设置位置和时间(如果有的话)。 我将创建 plunker 示例。同时,为了回答问题并更清楚地了解整个案例,最初,属性是空的,但是,从 ng-repeat 的角度来看,这是否是一个有效的情况?这可能是实际的问题 - 最初我有一个空数组的事实吗?父范围实际上已更新。指令的范围实际上与父控制器范围相同。我在指令中添加的这个手表实际上是在数据从服务器到达并添加到属性时触发的,因此我将排除范围问题。 我创建了一个plunker。在控制台中可以看到,在 3 秒(超时)后,属性的更改被指令内的 watchCollection 正确拾取,但它不适用于 ng-repeat。 【参考方案1】:

你来了

contentElement.replaceWith(clonedElement.html());

请注意,您实际上是用原始 HTML 字符串代码替换它。因此,Angular 在代码中没有指令的概念。但是,我根本不明白为什么需要这样做。只需编译并将结果附加到范围似乎就可以了:

var templateElement = angular.element(angular.element(element.children()[0]).children()[0]);
$compile(templateElement)(scope);

这是更新的工作版本:

http://plnkr.co/edit/gxPAP43sx3QxyFzBitd5?p=preview

$compile 的文档并没有说太多,但是 $compile 返回一个函数,然后您可以使用要附加元素的范围调用该函数(据我所知)。因此,您根本不需要存储对元素的引用,除非您以后想使用它。

【讨论】:

谢谢。如果不替换 HTML,我还没有尝试过。用我从$compile 得到的东西替换它是很自然的。而且,我已经多次阅读文档,只是为了确保我没有遗漏任何内容,但是,我显然要确定替换方法。

以上是关于AngularJS:ng-repeat 没有检测到范围的变化的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS ng-repeat 水平到垂直的重复项目

AngularJS数组到ng-repeat

嵌套 ng-repeat 的 AngularJS 记录计数

AngularJS:有没有办法使用ng-repeat从同一个数据数组创建行和列?

ng-repeat angularJS 中的 ng-repeat

angularjs如何在没有onclick的情况下增加ng-repeat中的init变量值?