javascript - 当新项目添加到模型时,ng-repeat 更改所有项目的排序顺序

标签 javascript angularjs angularjs-directive angularjs-ng-repeat transclusion

我创建了一个“tessellate”指令,可让您包装多个 div。

<tessellate columns="4">
  <div class="thumbnail" ng-repeat="item in items track by item.id">
      {{item.Name}}<br />
      {{item.Summary}}
  </div>
</tessellate>

它一次获取一个 div,并将其附加到指定列数中最短的列,以创建曲面分割/马赛克效果。

请在此处查看插件:http://plnkr.co/edit/ur0bVCFRSz1UbRHeLjz8?p=preview

问题在于,当模型发生变化时,ng-repeat 使用 div 在 DOM 中出现的顺序 而不是模型中的顺序来重绘元素。您可以看到项目首先正确排序,在单击 添加 后,它会水平排序第一列中的项目,然后是下一列中的项目,依此类推。

如何防止 ng-repeat 使用 DOM 顺序重绘元素?我已经尝试添加 orderBy item.id,但它没有帮助。

var app = angular.module('app', []);

app.controller('itemController', ['$scope', function ($scope) {
    $scope.items = [
             { id:"1", Name:"Item1", Summary:"This is the summary of Item1" },
             { id:"2", Name:"Item2", Summary:"This is the summary of Item2. Some extra text on item two to test different heights." },
             { id:"3", Name:"Item3", Summary:"This is the summary of Item3" },
             { id:"4", Name:"Item4", Summary:"This is the summary of Item4. Some extra text on item four to test different heights." },
             { id:"5", Name:"Item5", Summary:"This is the summary of Item5. Some extra text on item five to test different heights. Some extra text on item to test different heights." },
             { id:"6", Name:"Item6", Summary:"This is the summary of Item6" },
             { id:"7", Name:"Item7", Summary:"This is the summary of Item7. Some extra text on item seven to test different heights." },
             { id:"8", Name:"Item8", Summary:"This is the summary of Item8" },
             { id:"9", Name:"Item9", Summary:"This is the summary of Item9. Some extra text on item nine to test different heights." },
             { id:"10", Name:"Item10", Summary:"This is the summary of Item10. Some extra text on item ten to test different heights." },
             { id:"11", Name:"Item11", Summary:"This is the summary of Item11" },
             { id:"12", Name:"Item12", Summary:"This is the summary of Item12. Some extra text on item to test different heights." },
             { id:"13", Name:"Item13", Summary:"This is the summary of Item13" },
             { id:"14", Name:"Item14", Summary:"This is the summary of Item14. Some extra text on item to test different heights." },
             { id:"15", Name:"Item15", Summary:"This is the summary of Item15. Some extra text on item to test different heights. Some extra text on item to test different heights." },
             { id:"16", Name:"Item16", Summary:"This is the summary of Item16" },
             { id:"17", Name:"Item17", Summary:"This is the summary of Item17. Some extra text on item to test different heights." },
             { id:"18", Name:"Item18", Summary:"This is the summary of Item18" }
             ];
    $scope.inc = $scope.items.length;
    $scope.add = function() {
        $scope.inc = $scope.inc + 1;
        $scope.items.push({ id: $scope.inc, Name: "New Item" + $scope.inc, Summary:"New Summary" });
    };
}]);

app.directive('tessellate', [function () {
    return {
        restrict: 'E',
        replace: true,
        transclude: true,
        scope: {
            columns: '='
        },
        controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
            $scope.numberToArray = function (num) {
                return new Array(num);
            };
        }],
        link: function (scope, elem, attrs, ctrl) {

            scope.$watch(function () {
                return elem.children().first().height();
            }, function (height) {
                if (height > 0) {
                    var containers = elem.children();
                    var transcludedDivsContainer = containers.first();
                    var targetColumns = containers.eq(1).children();

                    // Add the transcluded divs one at a time into the shortest column.
                    angular.forEach(transcludedDivsContainer.children(), function (div) {
                        var shortCol = null;
                        angular.forEach(targetColumns, function (col) {
                            col = angular.element(col);
                            if (shortCol === null || col.height() < shortCol.height()) {
                                shortCol = col;
                            }
                        });
                        shortCol.append(div);
                    });
                }
            }
            );
        },
        templateUrl: "tessellateTemplate.html"
    };
}]);

最佳答案

我 fork 了你的 plunkr 并弄乱了它。我认为它现在可以按照您想要的方式工作。

http://plnkr.co/edit/1y8jE0SLuJK6XTNRBKF3?p=preview

主要修复它的是按索引对 dom 元素列表进行排序,为此我将 $index 添加到元素的数据索引属性中。

关于javascript - 当新项目添加到模型时,ng-repeat 更改所有项目的排序顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22973617/

相关文章:

javascript - 如何检查浏览器中消失的元素?

javascript - 在 angularjs 和 node.js 之间共享库的模式

javascript - 摊牌 Markdown 编辑器 : How to resize images to fit in with the content?

angularjs - 使用 ng-keyup 增加或减少输入的 ng-model

javascript - 使用 AngularJS 指令修改 Controller 数据

javascript - 使用 Object.create 时无法枚举属性

php - javascript无法从HTML输入标签分配隐藏的输入元素

javascript - angularJS 我可以在指令中使用参数吗?

javascript - 引用模块中的全局变量

javascript - 有没有什么方法可以在组件中要求一个不是来自另一个指令或组件的 Controller ?