Burak Akyıldız
Burak Akyıldız

Reputation: 1644

Angular material 1 / md-virtual-repeat select scroll

What is the right way to change md-virtual-repeat's scroll to watch events from an other scroll ?

I have tried some manual triggering

And i readed this question but it is not exactly i want.

So is there a way to select a scrool to virtual-repeat container ?

EDIT 2

I need to change scrollbar of virtual repeat with scrollbar of Body

Live example

(function() {
  'use strict';

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

  app.filter('to_trusted', ['$sce', function($sce) {
    return function(text) {
      return $sce.trustAsHtml(text);
    };
  }]);

  app.controller('AppCtrl', function($timeout) {
    this.itemSize = 529.39;

    var DynamicItems = function() {
      this.loadedPages = {};
      this.numItems = 0;
      this.PAGE_SIZE = 50;
      this.fetchNumItems_();
    };

    DynamicItems.prototype.getItemAtIndex = function(index) {
      var pageNumber = Math.floor(index / this.PAGE_SIZE);
      var page = this.loadedPages[pageNumber];

      if (page) {
        return page[index % this.PAGE_SIZE];
      } else if (page !== null) {
        this.fetchPage_(pageNumber);
      }
    };

    DynamicItems.prototype.getLength = function() {
      return this.numItems;
    };

    DynamicItems.prototype.fetchPage_ = function(pageNumber) {
      this.loadedPages[pageNumber] = null;

      $timeout(angular.noop, 300).then(angular.bind(this, function() {
        this.loadedPages[pageNumber] = [];
        var pageOffset = pageNumber * this.PAGE_SIZE;
        //console.log(pageNumber);

        for (var i = pageOffset; i < pageOffset + this.PAGE_SIZE; i++) {
          var obj = {};
          obj.name = 'Ad ' + i;
          obj.surname = 'Soyad ' + i;
          obj.age = i;
          obj.image = 'http://lorempixel.com/75/75/cats?' + i;
          obj.list = [];
          obj.clicked = false;
          obj.status = "asd";
          obj.html = '' + i + '---Lorem Ipsum, dizgi ve baskı endüstrisinde kullanılan mıgır metinlerdir. Lorem Ipsum, adı bilinmeyen bir matbaacının bir hurufat numune kitabı oluşturmak üzere bir yazı galerisini alarak karıştırdığı 1500 lerden beri endüstri standardı sahte metinler olarak kullanılmıştır. Beşyüz yıl boyunca varlığını sürdürmekle kalmamış, aynı zamanda pek değişmeden elektronik dizgiye de sıçramıştır. 1960 larda Lorem Ipsum pasajları da içeren Letraset yapraklarının yayınlanması ile ve yakın zamanda Aldus PageMaker gibi Lorem Ipsum sürümleri içeren masaüstü yayıncılık yazılımları ile popüler olmuştur.' + i;
          for (var j = 0; j < 1000; j++) {
            obj.list.push('http://lorempixel.com/75/75/city/?' + j);
          }

          this.loadedPages[pageNumber].push(obj);
        }

        //this.setItemNum(this.numItems + this.PAGE_SIZE);
      }));
    };

    DynamicItems.prototype.fetchNumItems_ = function() {
      $timeout(angular.noop, 300).then(angular.bind(this, function() {
        //console.log("fetchNumItems_");
        this.numItems = 10000;
      }));
    };

    DynamicItems.prototype.setItemNum = function(number) {
      this.numItems = number;
    };

    this.dynamicItems = new DynamicItems();
    //console.log(this.dynamicItems);
  });
}());
.virtualRepeatdemoDeferredLoading #vertical-container {
  width: 100%;
}
.virtualRepeatdemoDeferredLoading .repeated-item {
  border-bottom: 1px solid #ddd;
  box-sizing: border-box;
  padding-top: 10px;
}
.virtualRepeatdemoDeferredLoading md-content {
  margin: 16px;
}
.virtualRepeatdemoDeferredLoading md-virtual-repeat-container {
  border: solid 1px grey;
}
.virtualRepeatdemoDeferredLoading .md-virtual-repeat-container .md-virtual-repeat-offsetter div {
  padding-left: 16px;
}
.virtualRepeatdemoHorizontalUsage #horizontal-container {
  height: 100px;
  width: 100%;
}
.virtualRepeatdemoHorizontalUsage .repeated-item {
  border-right: 1px solid #ddd;
  box-sizing: border-box;
  display: inline-block;
  height: 84px;
  padding-top: 10px;
  text-align: center;
  width: 100px;
}
.virtualRepeatdemoHorizontalUsage md-content {
  margin: 16px;
}
.virtualRepeatdemoHorizontalUsage md-virtual-repeat-container {
  border: solid 1px grey;
}
<!DOCTYPE html>

<html class=''>

<head>
  <meta charset='UTF-8'>
  <meta name="robots" content="noindex">
  <link rel="shortcut icon" type="image/x-icon" href="//production-assets.codepen.io/assets/favicon/favicon-8ea04875e70c4b0bb41da869e81236e54394d63638a1ef12fa558a4a835f1164.ico" />
  <link rel="mask-icon" type="" href="//production-assets.codepen.io/assets/favicon/logo-pin-f2d2b6d2c61838f7e76325261b7195c27224080bc099486ddd6dccb469b8e8e6.svg" color="#111" />
  <link rel="canonical" href="http://codepen.io/anon/pen/OWXMXW" />
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700,400italic">
  <link rel='stylesheet prefetch' href='https://cdn.gitcdn.link/cdn/angular/bower-material/v1.1.1/angular-material.css'>
  <link rel='stylesheet prefetch' href='https://material.angularjs.org/1.1.1/docs.css'>
  <script src='https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.js'></script>
  <script src='https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-animate.min.js'></script>
  <script src='https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-route.min.js'></script>
  <script src='https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-aria.min.js'></script>
  <script src='https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-messages.min.js'></script>
  <script src='https://cdn.gitcdn.link/cdn/angular/bower-material/v1.1.1/angular-material.js'></script>

</head>

<body>
  <h1> Virtual Repeat Test </h1>
  <div ng-controller="AppCtrl as ctrl" ng-cloak="" flex layout-fill layout-padding class="virtualRepeatdemoDeferredLoading" ng-app="MyApp">

    <md-content layout="column" flex layout-fill>

      <md-virtual-repeat-container flex layout-fill md-auto-shrink="false" layout id="vertical-container">

        <div md-virtual-repeat="item in ctrl.dynamicItems" id="repeat_item" md-on-demand="true" md-item-size="ctrl.itemSize" layout-fill>

          <img ng-src="{{item.image}}" class="md-avatar" alt="{{item.name}}" />
          <br> Adı : {{item.name}} <br> Soyadı : {{item.surname}} <br> Yaşı : {{item.age}} <br> is Clicked : {{ item.clicked }} <br> status : {{ item.status }}
          <p ng-bind-html=" item.html | to_trusted "> </p>

          <h5 ng-click="item.clicked = !item.clicked; item.status = item.status + item.status; "> List Items </h5>

          <md-content ng-if="item.clicked == true" class="virtualRepeatdemoHorizontalUsage" layout="column">

            <md-virtual-repeat-container id="horizontal-container" md-orient-horizontal="">
              <div md-virtual-repeat="picture in item.list" class="repeated-item" flex="">
                <img ng-src="{{ picture }}" class="md-avatar" alt="{{ picture }}" />
              </div>
            </md-virtual-repeat-container>
          </md-content>

          <br>

        </div>

      </md-virtual-repeat-container>
    </md-content>

  </div>

</body>

</html>

Upvotes: 2

Views: 1737

Answers (1)

adam0101
adam0101

Reputation: 30995

If I understand your question correctly, you just want to scroll the virtual repeater div using a scrollbar somewhere else on your page? One way to do that would be to create a directive that listens to scroll event of the div you want to use as the visible scrollbar and then just scroll the other div the same percentage.

Here is one such directive. Add it to the md-virtual-repeat-container and point it to the div you want to scroll it. The divs can even be different heights.

Update I changed the directive to fall back to the body tag if an element wasn't specified.

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

app.controller("myController", function($scope) {
  $scope.items = [];
  for (var i = 0; i < 5000000; i++) {
    $scope.items.push(i);
  }
});

app.directive("scrollFrom", function($window, $document) {
  return {
    scope: {
      elTarget: '@scrollFrom'
    },
    link: function(scope, element, attrs) {
      var body = $document[0].body;
      angular.element(scope.elTarget || $window).bind("scroll", function() {
        var percentScrolled = scope.elTarget ?
          this.scrollHeight > 0 ? this.scrollTop / (this.scrollHeight - element.height()) : 0 :
          body.scrollHeight > 0 ? body.scrollTop / (body.scrollHeight - element.height()) : 0;
        var trgt = angular.element(element).find('.md-virtual-repeat-scroller')[0];
        trgt.scrollTop = trgt.scrollHeight * percentScrolled;
      });
    }
  };
});
#vertical-container {
  height: 292px;
  width: 100%;
  max-width: 400px;
  position: fixed;
  top: 10px;
}

#vertical-container .md-virtual-repeat-scroller {
  overflow: hidden;
}

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

md-virtual-repeat-container {
  border: solid 4px grey;
}
<html ng-app="myApp">

<head>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/angular-material/1.1.4/angular-material.min.css" />
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular-animate.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular-aria.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-material/1.1.4/angular-material.min.js"></script>
</head>

<body style="height: 5000000px">
  <div ng-controller="myController">
    <md-virtual-repeat-container id="vertical-container" scroll-from>
      <div md-virtual-repeat="item in items" class="repeated-item" flex>
        {{item}}
      </div>
    </md-virtual-repeat-container>
  </div>
</body>

</html>

Upvotes: 1

Related Questions