我尝试使用ngRepeat指令实现滚动到最后添加的条目。
我找到并调查了一些相关的SO问题:#1,#2。但仍然无法解决问题。
代码非常简单。 当用户向阵列添加新记录时,控制器广播“滚动事件”。使用新添加的项目名称,指令接收此事件并滚动到列表中新添加的条目。
<div ng-controller="MainCtrl">
<input ng-model="newItem" ng-keydown="$event.which === 13 && addNewItem(newItem)"/>
<button ng-click="addNewItem(newItem)">Add</button>
<div id="items-list" scroll-to-new-item>
<div ng-repeat="item in items | orderBy: 'name'">
<input ng-model="item.name" ng-readonly="true"/>
</div>
</div>
</div>
app.controller("MainCtrl", function($scope){
$scope.items = [
{id: 1, name: "aaa"}, {id: 2, name: "bbb"},
{id: 3, name: "ccc"}, {id: 4, name: "ddd"},
.......
];
$scope.addNewItem = function(newItem){
$scope.items.push({name: newItem});
$scope.$broadcast('scroll-event', newItem);
$scope.newItem = "";
};
});
这是我的指令,它应滚动到列表中最后添加的记录。
app.directive("scrollToNewItem", function(){
return {
restrict: 'A',
link: function(scope, element, attrs) {
scope.$on('scroll-event', function (event, newValue) {
if(newValue){
var newItemHeightPosition = // !!! MY ISSUE HERE !!!
$('#items-list').animate({
scrollTop: newItemHeightPosition
}, 'slow');
}
});
}
};
});
但我无法弄明白,如何获得新增项目的顶级位置。我尝试了几种变体,但它们没有得到任何结果。例如,以下jquery选择器不起作用:
$('#items-list').find('input[value=' + newValue +']');
$('#items-list').find('input').eq(newValue);
请注意,数组按字母顺序排序,因此会使此任务变得复杂。
谁知道,如何解决这个问题?
提前致谢!
答案 0 :(得分:1)
该代码存在两个问题。
1)第一个问题是,ngRepeat
指令在scrollToNewItem
指令开始之前没有在重复中呈现新添加的项目。
我已经通过$timeout中的DOM选择器包装来修复它。它提供了一种安全的方法来调用$ scope。$ apply并确保$ digest循环已经过去。您可以在此处阅读更多详细信息:Angular $scope.$apply vs $timeout as a safe $apply。
2)第二个问题与我的渲染输入项没有任何包含值的属性有关。因此,由于这个原因,我找不到任何带有以下JQuery选择器的DOM项。
$('#items-list').find('input[value=' + newValue +']')
我通过添加额外的属性value
来修复它,以输入whithin ngRepeat指令。
value="{{vehicle.Name}}"
最后,我编辑的 JSFiddle 与您可以找到here的工作示例。
答案 1 :(得分:0)
我不能提高效率,但除非你的名单在1000中,否则我个人不介意使用.each()这样的话。
app.directive("scrollToNewItem", function () {
return {
restrict: 'A',
link: function (scope, element, attrs) {
scope.$on('scroll-event', function (event, newValue) {
var newItemHeightPosition
if (newValue) {
$('#items-list input').each(function () {
if ($(this).html().indexOf(newValue)) {
newItemHeightPosition = $(this).position().top;
}
})
$('#items-list').animate({
scrollTop: newItemHeightPosition
}, 'slow');
}
});
}
};
});
进一步解释,在你自己的例子中,你写
$('#items-list').find('input[value=' + newValue +']');
你正在做的是尝试选择一个dom元素,例如看起来像这样
<input type="submit" value="name">
但是您的输入项目实际上甚至没有值属性。相反,我迭代输入并找到其html包含刚刚添加的名称的输入。它并不完美,但它应该说明如何解决您的问题。