Сортировка элементов в AngularJS для вложенного ng-repeat

Я использую bootstrap для отображения сетки проектов, в каждой строке которой есть 3 столбца. Для этого я использую ng-repeat дважды, как показано ниже.

<div class="row" ng-repeat="chunk in projects">
  <div class="col-sm-4" ng-repeat="project in chunk | orderBy:'title'">
    {{project.title}}
  </div>
</div>    

Я хочу иметь возможность сортировать проект на основе его поля заголовка. Применение фильтра сортирует только подмножество всего списка, т. е. сортирует на уровне блоков, а не на уровне проектов.

var projects = [[{"title":"Z"},{"title":"A"},{"title":"M"}],
  [{"title":"Z"},{"title":"A"},{"title":"M"}]];

После того, как произойдет orderBy, строки будут A M Z, A M Z. Как мне заставить его отображать A M Z, M Z Z?

Вот выброс для вышеуказанной проблемы. // РЕДАКТИРОВАТЬ: приведенный выше планк указывает на решение, потому что я обновил планк.


person Pravin Umamaheswaran    schedule 25.03.2016    source источник
comment
Почему вы ожидаете, что упорядочение внутреннего ng-repeat повлияет на внешний? Либо закажите внешний вид, либо подумайте о том, чтобы свести структуру данных к чему-то более близкому к вашему результату.   -  person David L    schedule 25.03.2016
comment
Да, вам нужно больше сгладить структуру.   -  person ryanyuyu    schedule 25.03.2016
comment
Насколько я понял, вы предлагаете мне изменять проекты как var = [{title:A},{title:B},{title:C},{title:A},{title:B},{title:C }]. Это создает проблему еще одну проблему. Я хочу, чтобы внешний div с классом row содержал ровно три внутренних div с классом col-sm-4. Это не может быть достигнуто с предлагаемой структурой данных.   -  person Pravin Umamaheswaran    schedule 25.03.2016


Ответы (3)


Вам понадобится собственный фильтр, который превратит ваши подмассивы в один массив. Весь смысл наличия отдельных массивов заключается в том, чтобы изолировать содержимое, что противоположно тому, что вы хотите.

Фильтр:

yourAppModule
.filter('titleSort', function(){
    return function(input){
        var fullArray = []; //Will be the output array    
        for(var i=0;i<input.length;i++)            
            fullArray.concat(input[i]);
            //Iterates through all the arrays in input (projects)
            //and merges them into one array            
        fullArray = fullArray.sort(function(a,b){return a.title>b.title});
            //Sorts it by the title property
        var chunks = [];
        var currentChunk;
        for(var i=0;i<fullArray.length;i++){
            if(i%3===0){
                currentChunk = [];
                chunks.push(currentChunk);
            }
            currentChunk.push(fullArray[i]);   
        }
        return chunks;
    };
} ...

Теперь ваш взгляд может быть таким:

<div class="col-sm-4" ng-repeat="project in projects | titleSort">
    {{project.title}}
</div>
person Harris    schedule 25.03.2016
comment
Я хочу, чтобы div со строкой класса содержал ровно 3 div с классом col-sm-4. Поэтому, если в переменной проектов более 3 проектов, я хочу, чтобы дополнительные проекты помещались в новый div со строкой класса. - person Pravin Umamaheswaran; 25.03.2016
comment
@PravinUmamaheswaran Я отредактировал его, чтобы повторно разделить весь массив после его сортировки. - person Harris; 25.03.2016
comment
Я попробовал ваше отредактированное решение. Я получаю сообщение об ошибке $rootScope.infdig. Оказывается, модель для ng-repeat продолжает меняться каждый раз, когда вызывается фильтр, что приводит к тому, что $digest вызывается бесконечное количество раз. Я пытаюсь решить эту проблему с помощью $scope.$watch. Обновлю, если найду решение. - person Pravin Umamaheswaran; 26.03.2016
comment
Хорошо, это звучит как проблема, не связанная с фильтром. То, что я дал, в конечном счете, является довольно простой перестановкой в ​​изолированной области. - person Harris; 26.03.2016

Наконец, я смог решить эту проблему с помощью цепочки фильтров. Я использовал модуль/библиотеку angular-filter, но это можно сделать даже без angular-filter.

<div class="container" ng-controller="ExampleController as exampleVm">
<div class="row" ng-repeat="chunk in exampleVm.projects|  chunkBy: 'title' | groupBy : 3">
  <div class="col-sm-4" ng-repeat="project in chunk">
    {{project.title}}
  </div>
</div>

I flattened the array and made it look like this.

var projects = [{"title:Z"},{"title":"A"},{"title":"M"},{"title:Z"},{"title":"A"},{"title":"M"}]

В цепочке фильтров я упорядочиваю элементы в сплющенном массиве сначала по заголовку, а затем делю его на подмассивы по 3 элемента в каждом. Надеюсь это поможет.

Планк можно найти здесь.

person Pravin Umamaheswaran    schedule 26.03.2016

попробуй это. может вам помочь.

var app = angular.module("app",[])
app.controller('ctrl',['$scope', function($scope){
        $scope.data = [[{"title":"Z"},{"title":"A"},{"title":"M"}],
  [{"title":"Z"},{"title":"A"},{"title":"M"}]];
  
  $scope.data2 = [];
  angular.forEach( $scope.data,function(d){
    angular.forEach(d,function(d1){
      $scope.data2.push(d1);
      })
    })
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<div ng-app="app" ng-controller="ctrl">
<div class="item item-checkbox">
   <div class="row">
  <div class="col-sm-4" ng-repeat="project in data2 | orderBy:'title'">
    {{project.title}}
  </div>
</div>    
</div>

person Hadi J    schedule 25.03.2016
comment
Я новичок в angular js и не совсем понял блок кода angular.forEach(). Я пытался использовать этот код как есть, но столбцы сетки не печатаются. Я не знаю, я что-то путаю или нет. - person Pravin Umamaheswaran; 26.03.2016