Синхронизация 2+ MD-Virtual-Повтор

0

Я хотел бы иметь возможность синхронизировать списки 2 md-virtual-repeat, чтобы их позиции прокрутки были идентичными.

Я пробовал использовать md-top-index, и это меня закрыло, но все равно, когда они прокручиваются, они не всегда выстраиваются в линию. http://codepen.io/anon/pen/NxKvmy

Изображение 174551

HTML

<div ng-app="virtualRepeatScrollToDemo" ng-controller="AppCtrl as ctrl" class="scroll-demo">
  <md-content class="md-padding">
    <div class="wrapper">
      <md-virtual-repeat-container id="vertical-container" md-top-index="ctrl.topIndex">
        <div md-virtual-repeat="item in ctrl.items"
            class="repeated-item" ng-class="{header: item.header}" flex>
          {{item.text}}
        </div>
      </md-virtual-repeat-container>
    </div>    
    <div class="wrapper">
      <md-virtual-repeat-container id="vertical-container" md-top-index="ctrl.topIndex">
        <div md-virtual-repeat="item in ctrl.items"
            class="repeated-item" ng-class="{header: item.header}" flex>
          {{item.text}}
        </div>
      </md-virtual-repeat-container>
    </div>    
  </md-content>
</div>

JS

(function () {
  'use strict';
    angular
      .module('virtualRepeatScrollToDemo', ['ngMaterial'])
      .controller('AppCtrl', function($scope) {
        this.years = [];
        this.items = [];
        var currentYear = new Date().getFullYear();
        var monthNames = ['January', 'February', 'March', 'April', 'May', 'June','July', 'August', 'September', 'October', 'November', 'December'];
        for (var y = currentYear; y >= (currentYear-20); y--) {
          this.years.push(y);
          this.items.push({year: y, text: y, header: true});
          for (var m = 11; m >= 0; m--) {
            this.items.push({year: y, month: m, text: monthNames[m]});
          }
        }    
      });
})();

CSS

.wrapper {
    width: 400px;
    float:left;
    margin-left:20px;
}

#vertical-container {
  height: 292px;
  width: 400px;
}

#vertical-container .repeated-item {
  border-bottom: 1px solid #ddd;
  box-sizing: border-box;
  height: 40px;
  padding-top: 10px;
}

#vertical-container .repeated-item.header {
    background-color: #3F51B5;
    color: white;
    text-align: center;
    font-weight: bold;
}

#vertical-container md-content {
  margin: 16px;
}

md-virtual-repeat-container {
  border: solid 1px grey;
}

.md-virtual-repeat-container .md-virtual-repeat-offsetter {
  padding-left: 16px;
}

Я искал хакерский способ сделать это, наблюдая за прокруткой/преобразованием позиций, но я не вижу способа сделать это. Кто-нибудь знает, как это сделать?

Благодарю.

Теги:
angular-material

1 ответ

1
Лучший ответ

Ниже приведена директива, которая синхронизирует виртуальные повторы. Вы используете его так:

<md-virtual-repeat-container md-orient-horizontal
    vr-scrollsync="scroll">
    <div md-virtual-repeat="...">
        ...
    </div>
</md-virtual-repeat-container>

В вашей области действия вы должны инициализировать свойство прокрутки пустым объектом:

$scope.scroll = {};

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

Я тестировал его с горизонтальными повторами, но он также должен работать на вертикали.


angular.module("vrScrollsync", []).directive("vrScrollsync", ["$timeout", function($timeout) {
    return {
        scope: {
            scroll: "=vrScrollsync"
        },
        link: function(scope, element, attrs) {
            /**
             * These flags avoid infinite recursion between Javascript 
             * event firing and Angular value changes.
             */
            var skipWatch = false;
            var skipEvent = false;

            /**
             * The scroller child of the virtual repeat container.
             * It is not there yet at link time, so we set up a timer to obtain it.
             */
            var scroller = null;

            $timeout(function() {
                scroller = element.find(".md-virtual-repeat-scroller");
                scroller.bind("scroll", function() {
                    if (skipEvent) {
                        skipEvent = false;
                        return;
                    }
                    update(true);
                });
            });

            function update(skipWatchIfChanged) {
                var oldval = scope.scroll; 
                var newval = {
                        top: scroller[0].scrollTop,
                        left: scroller[0].scrollLeft
                };
                scope.scroll = newval;

                var changed = oldval && (oldval.top != newval.top || oldval.left != newval.left)
                if (skipWatchIfChanged && changed) skipWatch = true;

                scope.$apply();
            }

            scope.$watch("scroll", function(v, old) {
                if (skipWatch) {
                    skipWatch = false;
                    return;
                }
                if (scroller) {
                    skipEvent = true;
                    scroller[0].scrollTop = v.top;
                    scroller[0].scrollLeft = v.left;
                }
            });
        }
    }; 
}]);
  • 0
    В течение нескольких дней я пытался внедрить ваше решение в несколько примеров, но пока не смог заставить его работать для любого из них. IE codepen.io/anon/pen/PZqqQW или codepen.io/anon/pen/NxKvmy Похоже, он ничего не делает.
  • 0
    Вероятно, проблема с версией jQuery. Я обновил этот: codepen.io/anon/pen/PZqzdd
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню