AngularJS:自定义指令不适用于 dirPagination
AngularJS: Custom directives not working with dirPagination
我正在使用 AngularJS 创建一个页面,其中包含一个产品列表,显示名称、价格、区域等信息。这显示有点像手风琴,名称在 header 和 body 中的额外信息。
由于可能会显示大量这些项目,因此我使用 dirPagination (https://github.com/michaelbromley/angularUtils/tree/master/src/directives/pagination) 对这些项目进行分页。我现在的标记如下所示:
<div class="custom-list" dir-paginate="asset in assets | itemsPerPage: 10 track by $index">
<div class="custom-list-item" ng-class="{'tag-hover': isHoveredTag(asset)}">
<div class="custom-list-item-heading" ng-click="toggleShowAssetDetails(asset)">
<p class="col-lg-5">{{ asset.name }}</p>
<div class="col-lg-offset-2 col-lg-3 rating">
<rating value="asset.rating" />
</div>
<button ng-click="addAsset(asset)"><span class="glyphicon glyphicon-plus"></span></button>
<div class="clearfix"></div>
</div>
<div class="custom-list-item-content" style="display: none" animate="shouldShowAssetDetails(asset)">
...
</div>
</div>
</div>
如您所见,我正在以一种非常标准的方式使用分页,只是循环遍历数组中的项目并每页显示 10 个。我还有一个名为 rating 的指令,它查看项目中名为 rating 的值。这是一个 1 - 5 的数字,用于在名称旁边显示星级系统。该指令如下所示:
var rating = function ($compile) {
return {
restrict: "E",
scope: {
value: "="
},
link: function (scope, element, attrs) {
scope.$watch(attrs.rating, function () {
for (var i = 1; i <= 5; i++) {
if (i <= scope.value) {
var starElement = angular.element("<span class=\"icon icon-crown\"></span>");
$compile(starElement)(scope);
element.append(starElement);
} else {
var emptyStarElement = angular.element("<span class=\"icon-empty icon-crown\"></span>");
$compile(emptyStarElement)(scope);
element.append(emptyStarElement);
}
}
})
}
}
}
这会查看值并根据评级值插入图标(例如,如果评级为 2,指令将插入两个 icon-crown 图标范围和 3 icon-empty icon-crown 图标跨度。
在我包含分页之前,这工作得很好。但是现在它只适用于前 10 个项目。当您更改页面时,评级不会改变,只会保留与上一页相同的图标,即使值不同也是如此。
我知道这是因为该指令在开始时设置了所有内容,当您更改页面时它不会 运行 因为项目不会重新加载它们只是再次显示和隐藏。但是该指令正在操纵 DOM,因此它不会在页面更改时更新。
问题是我不知道如何解决这个问题。我考虑过更改指令以查找分页当前页面,但后来我无权访问当前列表项。
对于在页面更改时获取更新图标的指令的任何帮助,我将不胜感激。
更新
这是一个 Plunker 项目的 link,显示了我遇到的问题:http://plnkr.co/edit/VSQ20eWCwVpaCoS7SeQq?p=preview
这是我遇到问题的应用程序部分的精简版。尽管我保留了 CSS class 结构,但没有包含任何样式。我还更改了图标以使用 bootstrap 图标来简化 Plunker 项目。
但是功能是一样的。如果您从第 1 页转到第 2 页,请注意尽管资产评级值不同,但星星如何保持不变。但是,如果您转到第 3 页并返回第 2 页或第 1 页,它们将会改变。发生这种情况的原因是因为第 3 页上的项目较少,因此当您返回第 1 或 2 页时,将再次调用剩余的项目以检索评分值。
您只需删除或替换 track by $index
。
$index
的跟踪会给您带来以下行为:
有一个最大长度为 10 的数组,表示要显示的项目。第一项的索引为 0。
您转到下一页,数组中的项目被替换。
数组中的第一项仍将具有索引 0。由于您正在按索引跟踪并且索引未更改,因此 AngularJS 将不会重新创建表示该项目的 DOM 节点。由于未重新创建 DOM 节点,因此这次指令不会执行,评级也不会更新。
如果从第 3 页转到第 2 页,指令将执行第 2 页的最后 7 个元素,因为它们在第 3 页不存在,所以这次它们被认为是新的。
如果你真的需要使用track by
,你应该使用与对象实际相关(且唯一)的属性,例如:
dir-paginate="asset in assets | itemsPerPage: 10 track by asset.name"
我正在使用 AngularJS 创建一个页面,其中包含一个产品列表,显示名称、价格、区域等信息。这显示有点像手风琴,名称在 header 和 body 中的额外信息。
由于可能会显示大量这些项目,因此我使用 dirPagination (https://github.com/michaelbromley/angularUtils/tree/master/src/directives/pagination) 对这些项目进行分页。我现在的标记如下所示:
<div class="custom-list" dir-paginate="asset in assets | itemsPerPage: 10 track by $index">
<div class="custom-list-item" ng-class="{'tag-hover': isHoveredTag(asset)}">
<div class="custom-list-item-heading" ng-click="toggleShowAssetDetails(asset)">
<p class="col-lg-5">{{ asset.name }}</p>
<div class="col-lg-offset-2 col-lg-3 rating">
<rating value="asset.rating" />
</div>
<button ng-click="addAsset(asset)"><span class="glyphicon glyphicon-plus"></span></button>
<div class="clearfix"></div>
</div>
<div class="custom-list-item-content" style="display: none" animate="shouldShowAssetDetails(asset)">
...
</div>
</div>
</div>
如您所见,我正在以一种非常标准的方式使用分页,只是循环遍历数组中的项目并每页显示 10 个。我还有一个名为 rating 的指令,它查看项目中名为 rating 的值。这是一个 1 - 5 的数字,用于在名称旁边显示星级系统。该指令如下所示:
var rating = function ($compile) {
return {
restrict: "E",
scope: {
value: "="
},
link: function (scope, element, attrs) {
scope.$watch(attrs.rating, function () {
for (var i = 1; i <= 5; i++) {
if (i <= scope.value) {
var starElement = angular.element("<span class=\"icon icon-crown\"></span>");
$compile(starElement)(scope);
element.append(starElement);
} else {
var emptyStarElement = angular.element("<span class=\"icon-empty icon-crown\"></span>");
$compile(emptyStarElement)(scope);
element.append(emptyStarElement);
}
}
})
}
}
}
这会查看值并根据评级值插入图标(例如,如果评级为 2,指令将插入两个 icon-crown 图标范围和 3 icon-empty icon-crown 图标跨度。
在我包含分页之前,这工作得很好。但是现在它只适用于前 10 个项目。当您更改页面时,评级不会改变,只会保留与上一页相同的图标,即使值不同也是如此。
我知道这是因为该指令在开始时设置了所有内容,当您更改页面时它不会 运行 因为项目不会重新加载它们只是再次显示和隐藏。但是该指令正在操纵 DOM,因此它不会在页面更改时更新。
问题是我不知道如何解决这个问题。我考虑过更改指令以查找分页当前页面,但后来我无权访问当前列表项。
对于在页面更改时获取更新图标的指令的任何帮助,我将不胜感激。
更新 这是一个 Plunker 项目的 link,显示了我遇到的问题:http://plnkr.co/edit/VSQ20eWCwVpaCoS7SeQq?p=preview
这是我遇到问题的应用程序部分的精简版。尽管我保留了 CSS class 结构,但没有包含任何样式。我还更改了图标以使用 bootstrap 图标来简化 Plunker 项目。
但是功能是一样的。如果您从第 1 页转到第 2 页,请注意尽管资产评级值不同,但星星如何保持不变。但是,如果您转到第 3 页并返回第 2 页或第 1 页,它们将会改变。发生这种情况的原因是因为第 3 页上的项目较少,因此当您返回第 1 或 2 页时,将再次调用剩余的项目以检索评分值。
您只需删除或替换 track by $index
。
$index
的跟踪会给您带来以下行为:
有一个最大长度为 10 的数组,表示要显示的项目。第一项的索引为 0。
您转到下一页,数组中的项目被替换。
数组中的第一项仍将具有索引 0。由于您正在按索引跟踪并且索引未更改,因此 AngularJS 将不会重新创建表示该项目的 DOM 节点。由于未重新创建 DOM 节点,因此这次指令不会执行,评级也不会更新。
如果从第 3 页转到第 2 页,指令将执行第 2 页的最后 7 个元素,因为它们在第 3 页不存在,所以这次它们被认为是新的。
如果你真的需要使用track by
,你应该使用与对象实际相关(且唯一)的属性,例如:
dir-paginate="asset in assets | itemsPerPage: 10 track by asset.name"