0

Я использую AngularJS для создания страницы, содержащей список продуктов, который показывает информацию, такую ​​как имя, цена, регион и т. Д. Это отображается как аккордеон с именем в заголовок и дополнительную информацию в теле.AngularJS: Пользовательские директивы, не работающие с dirPagination

Поскольку может отображаться большое количество этих предметов, я использую dirPagination (https://github.com/michaelbromley/angularUtils/tree/master/src/directives/pagination) для разбивки на эти элементы. Моя наценка на данный момент выглядит следующим образом:

<div class="custom-list" dir-paginate="asset in assets | itemsPerPage: 10 track by $index"> 
    <div class="custom-list-item" ng-class="{'tag-hover': isHoveredTag(asset)}"> 
     <div class="custom-list-item-heading" ng-click="toggleShowAssetDetails(asset)"> 
      <p class="col-lg-5">{{ asset.name }}</p> 
      <div class="col-lg-offset-2 col-lg-3 rating"> 
       <rating value="asset.rating" /> 
      </div> 
      <button ng-click="addAsset(asset)"><span class="glyphicon glyphicon-plus"></span></button> 
      <div class="clearfix"></div> 
     </div> 
     <div class="custom-list-item-content" style="display: none" animate="shouldShowAssetDetails(asset)"> 
      ... 
     </div> 
    </div> 
</div> 

Как вы можете видеть, я использую постраничной в довольно стандартным способом просто зацикливание по элементам массива и отображения 10 на каждой странице. У меня также есть директива, называемая рейтингом, которая рассматривает значение, называемое рейтингом в элементе. Это число от 1 до 5, которое используется для отображения звездной системы рядом с именем. Директива выглядит следующим образом:

var rating = function ($compile) { 
    return { 
     restrict: "E", 
     scope: { 
      value: "=" 
     }, 
     link: function (scope, element, attrs) { 
      scope.$watch(attrs.rating, function() { 
       for (var i = 1; i <= 5; i++) { 
        if (i <= scope.value) { 
         var starElement = angular.element("<span class=\"icon icon-crown\"></span>"); 
         $compile(starElement)(scope); 
         element.append(starElement); 
        } else { 
         var emptyStarElement = angular.element("<span class=\"icon-empty icon-crown\"></span>"); 
         $compile(emptyStarElement)(scope); 
         element.append(emptyStarElement); 
        } 
       } 
      })    
     } 
    } 
} 

Это смотрит на значение и вставляет значки, основанные на значении рейтинга (например, если оценка была 2 директива будет вставить два значка значок-краун пролеты и 3 значка пусто icon-crown icon spans.

Это было прекрасно, прежде чем я включил разбивку на страницы. Однако теперь он будет работать только для первых 10 предметов. Когда вы меняете страницу, рейтинг не изменится и просто сохранит одинаковые значки от предыдущей страницы, даже если значения различны.

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

Проблема в том, что я не знаю, как это решить. Я думал об изменении директивы для поиска текущей страницы страницы, но тогда у меня нет доступа к текущему элементу списка.

Буду признателен за получение директивы по обновлению значков при изменении страницы.

Update Вот ссылка на проект Plunker показывающий меня проблема: http://plnkr.co/edit/VSQ20eWCwVpaCoS7SeQq?p=preview

Это очень урезанную версию раздела на мое приложение, что у меня проблема с. Там нет стиля, хотя я сохранил структуру класса CSS. Я также изменил значки, чтобы использовать бутстрап только для упрощения проекта Plunker.

Функциональность такая же. Если вы переходите со страницы 1 на страницу 2, обратите внимание на то, как звезды остаются прежними, несмотря на то, что значения рейтинга активов различны. Однако, если перейти на страницу 3 и вернуться на страницу 2 или 1, они будут изменены. Причина этого в том, что на странице 3 меньше предметов, поэтому, когда вы вернетесь на страницу 1 или 2, остальные предметы будут вызываться снова, чтобы получить значения рейтинга.

+0

Можете ли вы повторить его в Plunker и поделитесь ссылкой? Это значительно повысит вероятность того, что кто-то помог, так как они могут поиграть и попробовать разные решения. – tasseKATT

+0

Я включил ссылку на Plunker в своем оригинальном посте – Serberuss

+0

Отлично, посмотрим на это. – tasseKATT

ответ

1

Вам просто нужно удалить или заменить track by $index.

Отслеживать $index даст вам следующее поведение:

Там есть массив максимальной длиной 10, который представляет элементы, чтобы показать. Первый элемент будет иметь индекс 0.

Вы переходите на следующую страницу, и элементы в массиве заменяются.

Первый элемент массива будет по-прежнему иметь индекс 0. Поскольку вы отслеживаете по индексу и индекс не изменился, AngularJS не воссоздает узел DOM, представляющий элемент. Поскольку узел DOM не воссоздается, директива не будет выполняться на этот раз, и рейтинг не будет обновляться.

Если вы переходите со страницы 3 на страницу 2, директива будет выполняться для 7 последних элементов на стр. 2, так как их не было на странице 3, поэтому на этот раз они считаются новыми.

Если вам действительно нужно использовать track by следует использовать свойство, которое на самом деле связано с объектом (и уникальным), например:

dir-paginate="asset in assets | itemsPerPage: 10 track by asset.name" 

Демо:http://plnkr.co/edit/A80tSEliUkG5idBmGe3B?p=preview

+0

Удивительная благодарность за то, что я пытался понять это в течение часа – Serberuss

+0

Добро пожаловать :) Это сложная проблема, с которой многие сталкиваются. – tasseKATT

+0

@tasseKATT Я использую директиву dir-paginate для моего приложения. Я хочу знать, есть ли способ получить текущие страницы текущей страницы в объекте? Я извиняюсь за то, что написал здесь, но думал, что это хороший способ подключения. –

Смежные вопросы