【问题标题】:Scroll to the last added record in the array within ng-repeat滚动到 ng-repeat 中数组中最后添加的记录
【发布时间】:2015-11-22 20:50:04
【问题描述】:

我尝试通过 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);

请注意,数组是按字母顺序排序的,这会使这项任务复杂化。

This is my JSFiddle.

谁知道,如何解决这个问题?

提前致谢!

【问题讨论】:

  • 你确定 "$('#items-list').find('input[value=' + newValue +']');"是不是写错了? ('input[value=' + newValue +']') 应该是 ('input[value="' + newValue +'"]') 正确使用 " 在 newValue 的每一侧
  • @NachoDawg,没关系。还是不行。
  • 好的。你能解释一下附加项目后dom的样子吗? newValue 变量是项目类吗?还是一个属性?
  • @NachoDawg。这是输入值。你可以在我的 JSFiddle 中看到它jsfiddle.net/k66Za/128
  • @gbalduzzi。请仔细阅读我的问题。它不能解决我的问题。

标签: javascript jquery css angularjs


【解决方案1】:

那段代码有两个问题。

1) 第一个问题是因为ngRepeat 指令在scrollToNewItem 指令开始之前没有在repeat 中呈现新添加的项目。

我已经通过在$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

【讨论】:

    【解决方案2】:

    我不考虑效率,但除非您的列表数字在 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">
    

    但是您的 input-items 实际上甚至没有 value 属性。相反,我遍历输入并找到其 html 包含刚刚添加的名称的那个。它并不完美,但它应该说明您可以如何解决您的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-10-28
      • 1970-01-01
      • 2013-06-22
      • 2017-07-24
      • 2013-04-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多