AngularJS: пользовательские итерации/преобразования данных и группировка, когда простой ng-repeat просто не поможет.

Тем не менее эта проблема Angular.js более сложные условные циклы, но я чувствовал, что ответ на заданный вопрос был правильным, поэтому Я принял это.

Итак, позвольте мне уточнить больше, чем я сделал в исходном вопросе.

я пытаюсь получить это

<h3>11.4.2013</h3>
<ul>
 <li>oofrab | 4 | 11.4.2013 14:55 <button>remove</button></li>
 <li>raboof | 3 | 11.4.2013 13:35 <button>remove</button></li>
</ul>

<h3>10.4.2013</h3>
<ul>
 <li>barfoo | 2 | 10.4.2013 18:10 <button>remove</button></li>
 <li>foobar | 1 | 10.4.2013 12:55 <button>remove</button></li> 
</ul>

из этой структуры данных

[
    {
        "id": 4,
        "name": "oofrab",
        "date": "2013-11-04 14:55:00"
    },
    {
        "id": 3,
        "name": "raboof",
        "date": "2013-11-04 13:55:00"
    },
    {
        "id": 2,
        "name": "barfoo",
        "date": "2013-10-04 18:10:00"
    },
    {
        "id": 1,
        "name": "foobar",
        "date": "2013-10-04 12:55:00"
    }
]

По сути, единственное дополнение к стандартному ng-repeat, которое я хочу добавить, это заголовки. И я просто не могу поверить, что мне пришлось бы преодолевать столько проблем, добавляя их.

Вот к чему я пришел, используя ответ, полученный в первом вопросе http://plnkr.co/edit/Zl5EcsiXXV92d3VH9Hqk?p=preview

Обратите внимание, что реально может быть до 400 записей. И мне нужно иметь возможность добавлять/удалять/редактировать записи на лету

Вот что делает пример на plunker:

итерация исходных данных с созданием новой структуры данных, похожей на эту

{
  "2013-10-05": [
    {
      "id": 4,
      "name": "oofrab",
      "date": "2013-10-05 14:55:00",
      "_orig_index": 0
    },
    {
      "id": 3,
      "name": "raboof",
      "date": "2013-10-05 13:55:00",
      "_orig_index": 1
    }
  ],
  "2013-10-04": [
    {
      "id": 2,
      "name": "barfoo",
      "date": "2013-10-04 18:10:00",
      "_orig_index": 2
    },
    {
      "id": 1,
      "name": "foobar",
      "date": "2013-10-04 12:55:00",
      "_orig_index": 3
    }
  ]
}

позволив мне затем получить желаемый результат

<div ng-repeat="(date,subItems) in itemDateMap">
<h3>{{date}}</h3>
<ul>
  <li ng-repeat="item in subItems">
    {{item.name}} | {{item.id}} | {{item.date}}
    <button type="button" ng-click="removeItem(item._orig_index)">x</button>
  </li>
</ul>  
</div>

Отлично. Но за это приходится платить кучу проблем. Каждый раз, когда добавляется новый элемент, мне приходится перестраивать itemDateMap, каждый раз, когда элемент удаляется, мне приходится перестраивать itemDateMap, каждый раз, когда меняется дата, мне приходится перестраивать itemDateMap. Когда я хочу удалить элемент, я должен сначала получить индекс его исходной ссылки. И каждый раз, когда itemDateMap перестраивается, все это перерисовывается. И его нельзя отсортировать, так как это объект, а не массив.

Когда есть пара сотен записей, это также становится очень, очень медленным. Я где-то читал, что ng-repeat довольно умный, отслеживает значения, перемещает кивки в dom, а не перерисовывает все и прочее, но это точно не работает, когда я перестраиваю всю структуру.

Этого не может быть, все эти хлопоты, чтобы сделать очень, очень простую вещь..

Что я должен делать?


person fxck    schedule 11.04.2013    source источник
comment
вы можете улучшить производительность, отредактировав карту, а не создавая ее каждый раз   -  person Arun P Johny    schedule 12.04.2013
comment
как бы я это сделал, учитывая, что новая запись может быть добавлена ​​​​в середину массива. Мне нужно будет пройти через itemDateMap, найти, есть ли день, который == с датой новой записи, если нет, добавьте его в соответствующую позицию, если день уже есть, прокрутите его элементы и добавьте их в соответствующую позицию.. черт возьми, это еще много, чтобы сделать простую группировку элементов. поэтому я не могу легко редактировать его..   -  person fxck    schedule 12.04.2013
comment
@foxx вы думали о создании нескольких объектов (например, на каждый день) вместо одного большого? Я мог бы представить, что это улучшит производительность, если у вас 400 записей (или больше), так как только ng-repeat за день должен быть перестроен при редактировании.   -  person F Lekschas    schedule 12.04.2013
comment
Структура данных, которую вы видите, это то, что я получаю от сервера, и она не изменится. Но я предполагаю, что то, что вы говорите, в основном то, что происходит в любом случае, этот большой объект разбит на дни инициализации, с записями для каждого дня в нем.   -  person fxck    schedule 12.04.2013


Ответы (1)


Это мое предложение - просто работайте с одной структурой и выставляйте только одну структуру в область действия (карту). И создайте функцию для добавления массива элементов на карту и функцию, которая преобразует карту в массив (я предполагаю, что вам нужен этот массив для связи с сервером или что-то в этом роде).

  var toKey=function(item){
    return moment(item.date).format("YYYY-MM-DD");
  }

  $scope.itemDateMap = {};
  $scope.addItemToDateMap=function(item){
    var key = toKey(item);
    if(!$scope.itemDateMap[key]){
      $scope.itemDateMap[key] = [];
    }
    $scope.itemDateMap[key].push(item);    
  }

  $scope.removeItemFromDateMap=function(item){
    var key = toKey(item), subitems = $scope.itemDateMap[key];
    var index = subitems.indexOf(item);
    subitems.splice(index,1);
    if(subitems.length === 0){
      delete $scope.itemDateMap[key];
    }
  }

  var addArrayToMap = function(items){
    for(var i=0; i<items.length; i++){
      var item = items[i]; 
      $scope.addItemToDateMap(item);
    }
  };

  $scope.mapToArray = function(){
    var items = [];
    for(var key in $scope.itemDateMap){
      var subitems = $scope.itemDateMap[key];
      for(var j=0;j<subitems.length;j++){
        var item = subitems[j];
        items.push(item);
      }
    }
    return items;
  }

Я обновил ваш plnkr с моим предложением. Я думаю, что он работает достаточно хорошо.

О, я только что заметил, что вы хотите отсортировать его - у меня нет времени обновлять мой пример, но он не очень сложный. Вместо этого используйте эту структуру (массив с объектами с массивами вместо объекта с массивом) - таким образом вы можете использовать orderBy:'date' в корневом массиве:

[
{
  date:"2013-10-05",
  items: [
    {
      "id": 4,
      "name": "oofrab",
      "date": "2013-10-05 14:55:00"
    },
    {
      "id": 3,
      "name": "raboof",
      "date": "2013-10-05 13:55:00"
    }
  ]
},
{
date:"2013-10-04",
items: [
    {
      "id": 2,
      "name": "barfoo",
      "date": "2013-10-04 18:10:00"
    },
    {
      "id": 1,
      "name": "foobar",
      "date": "2013-10-04 12:55:00"
    }
  ]
}
]
person joakimbl    schedule 12.04.2013
comment
Выглядит хорошо, это определенно немного быстрее, чем раньше. Есть еще одна чертова проблема, которую это не решит, и это изменение даты элемента, что должно переместить элемент / создать новый день. - person fxck; 12.04.2013
comment
Именно поэтому у меня была эта директива onblur. Но я решил это, используя ваши функции удаления и добавления - person fxck; 12.04.2013
comment
хотя массив с объектами с массивами сломал бы все функции, которые вы сделали... не так ли? - person fxck; 12.04.2013
comment
А, понятно, я забыл о переупорядочивании после смены даты, извините. Использование добавления/удаления кажется разумным подходом. И да, вам придется внести некоторые изменения — у меня сейчас нет на это времени, но они не должны быть слишком сложными. - person joakimbl; 12.04.2013
comment
В конце немного изменил его, но это определенно помогло мне, спасибо. До сих пор довольно грустно, что приходится делать так много всего лишь для того, чтобы иметь возможность группировать вещи. - person fxck; 13.04.2013