NgRepeat'in büyük bir veri kümesi (angular.js) üzerindeki performansı nasıl artırılır?


165

Her biri yaklaşık 10 alan, yaklaşık 2MB veri içeren birkaç bin satırlık büyük bir veri setim var. Tarayıcıda göstermem gerekiyor. En basit yaklaşım (veri getir, içine koy , işini $scopeyapalım ng-repeat="") iyi çalışıyor, ancak DOM'a düğüm eklemeye başladığında tarayıcıyı yaklaşık yarım dakika donduruyor. Bu soruna nasıl yaklaşmalıyım?

Seçeneklerden biri, satırları $scopeaşamalı olarak eklemek ve ngRepeatbir sonrakine geçmeden önce bir parçayı DOM'a eklemeyi bitirmek için beklemektir . Ancak AFAIK ngRepeat "tekrarlama" bittiğinde rapor vermez, bu yüzden çirkin olur.

Diğer seçenek, sunucudaki verileri sayfalara bölmek ve birden fazla istekte almaktır, ancak bu daha çirkin.

Açısal belgelere baktım ng-repeat="data in dataset" ng-repeat-steps="500", ama böyle bir şey aradım ama hiçbir şey bulamadım. Açısal yollarda oldukça yeniyim, bu yüzden noktayı tamamen kaçırmam mümkündür. Bu konuda en iyi uygulamalar nelerdir?


10
Gerçekten TÜM satırları görüntülemek istiyor musunuz? Yalnızca kullanıcının görebileceği çok sayıda satırı görüntülemeye ne dersiniz? örneğin limitToyalnızca 20 öğeyi görüntülemek için kullanabilirsiniz : <p ng-repeat="data in dataset | limitTo:20">{{data}}</p>Bu yalnızca 20 öğeyi gösterir. Ardından sayfaları kullanabilir ve sonraki 10 öğeyi veya bunun gibi bir şeyi gösterebilirsiniz. :)
AndreM96

"tekrarlayan" işlemi tekrarladığında "ng-repeat 'a ek olarak özel bir direktif de kullanabilirsiniz. (seçilen cevaba bakın) stackoverflow.com/questions/13471129/…
mayankcpdixit

bu soruya kesinlikle yardımcı olacaktır. [buraya bağlantı açıklamasını girin] [1] [1]: stackoverflow.com/questions/25481021/…
Mahesh

Yanıtlar:


159

@ AndreM96 ile en iyi yaklaşımın sadece sınırlı sayıda satır, daha hızlı ve daha iyi UX görüntülemek olduğuna katılıyorum, bu bir sayfalama veya sonsuz bir kaydırma ile yapılabilir.

Angular ile sonsuz kaydırma limitTo filtresi ile gerçekten basittir . Sadece başlangıç ​​sınırını ayarlamanız gerekir ve kullanıcı daha fazla veri istediğinde (basitlik için bir düğme kullanıyorum) sınırı artırırsınız.

<table>
    <tr ng-repeat="d in data | limitTo:totalDisplayed"><td>{{d}}</td></tr>
</table>
<button class="btn" ng-click="loadMore()">Load more</button>

//the controller
$scope.totalDisplayed = 20;

$scope.loadMore = function () {
  $scope.totalDisplayed += 20;  
};

$scope.data = data;

İşte bir JsBin .

Bu yaklaşım telefonlar için bir sorun olabilir, çünkü genellikle çok fazla veri kaydırırken gecikirler, bu durumda bir sayfalama daha iyi uyuyor.

Bunu yapmak için limitTo filtresine ve ayrıca görüntülenmekte olan verinin başlangıç ​​noktasını tanımlamak için özel bir filtreye ihtiyacınız olacaktır.

İşte sayfalandırmalı bir JSBin .


Güzel bir alternatif !!! Tüm öğeleri göstermek zorundayım kullanmak için herhangi bir yöntem biliyorsunuz. herhangi bir yükleme işareti veya DOM veya bir şey yerleştirildikten sonra bir?
mayankcpdixit

Veriler getirilirken "yükleniyor ..." veya başka bir şey görüntülemeyi mi kastediyorsunuz?
Bertrand

1
@ Yineleme limiti ng yineleme kapsamına uygulanacağı için sonuç ng yineleme işlemine geçirilecek yeni bir dizi olacaktır, veri diziniz hala aynıdır ve yine de tüm içeriği arayabilirsiniz.
Bertrand

12
kullanıcı 10 kez daha basar ve her basışta 100 öğe daha eklerse, bu performansı nasıl artırabilir?
hariszaman

5
@hariszaman katılıyorum. Bu performansı artırmaz. Kötü performansı geciktirir. Sonsuz kaydırma, sanallaştırmadığınız sürece (bu ui-grid'in yaptığı) sizi derde sokar.
richard

41

Büyük veri kümeleriyle bu zorlukların üstesinden gelmek için en sıcak ve tartışmasız en ölçeklenebilir yaklaşım, Ionic'in collectionRepeat yönergesi ve bunun gibi diğer uygulamaların yaklaşımı ile şekillenir . Bunun için süslü bir terim 'tıkanıklık ayıklamasıdır' , ancak şu şekilde özetleyebilirsiniz: işlenen DOM öğelerinin sayısını yalnızca 50, 100, 500 gibi rastgele (ama yine de yüksek) sayfalandırılmış bir sayıyla sınırlamayın ... , yalnızca kullanıcının görebildiği kadar çok öğeyle sınırlandırın .

Yaygın olarak "sonsuz kaydırma" olarak bilinen bir şey yaparsanız, ilk DOM sayısını bir miktar azaltırsınız, ancak birkaç yenilemeden sonra hızla şişer, çünkü tüm bu yeni öğeler en altta tutturulur. Kaydırma bir taramaya gelir, çünkü kaydırma tamamen öğe sayımı ile ilgilidir. Bu konuda sonsuz bir şey yok.

Oysa collectionRepeatyaklaşım, yalnızca görüntü alanına sığacak kadar çok eleman kullanmak ve bunları geri dönüştürmektir . Bir öğe görünümden döndükçe, oluşturma ağacından ayrılır, listedeki yeni bir öğe için verilerle doldurulur, ardından listenin diğer ucundaki oluşturma ağacına yeniden bağlanır. Bu, insanın DOM'da ve dışında yeni bilgi alması için bilinen en hızlı yoldur, geleneksel oluşturma / yok etme / oluşturma / yok etme döngüsünden ziyade mevcut öğelerin sınırlı bir setini kullanır. Bu yaklaşımı kullanarak, gerçekten sonsuz bir kaydırma uygulayabilirsiniz .

İyonik / hack / adapte collectionRepeatveya bunun gibi başka bir araç kullanmak zorunda değilsiniz . Bu yüzden buna açık kaynak diyorlar. :-) (Bu, İyonik ekibin dikkatinize layık bazı ustaca şeyler yaptığını söyledi.)


React'te çok benzer bir şey yapmanın en az bir mükemmel örneği var . Yalnızca güncellenmiş içeriğe sahip öğeleri geri dönüştürmek yerine, ağaçta görüntülenmeyen hiçbir şey oluşturmamayı seçersiniz. Çok basit POC uygulamaları biraz titremeye izin verse de 5000 öğe üzerinde hızlı yanıp sönüyor ...


Ayrıca ... diğer yazıların bazılarını yankılanmak için track by, küçük veri kümelerinde bile kullanmak gerçekten yararlıdır. Zorunlu olduğunu düşünün.


İyonik ekip tarafından harika bir fikir. Bunun yerel görünümlerin nasıl oluşturulduğundan geldiğini merak ediyorum.
Bradley Flood

Örneğin, iOS'taki UITableView, büyük veri kümeleri oluşturmak için aynı yaklaşımı kullanır. Bence bu birçok yerel görüşte kullanılan ortak bir yaklaşım.
Dmitry Kotenko

36

Bunu görmenizi tavsiye ederim:

Açısal JS'yi optimize etme: 1200ms - 35ms

4 parçalı tekrarlamayı optimize ederek yeni bir yönerge hazırladılar:

Optimizasyon # 1: DOM öğelerini önbelleğe al

Optimizasyon # 2: Toplu gözlemciler

Optimizasyon # 3: Eleman oluşturmayı ertele

Optimizasyon # 4: Gizli öğeler için izleyicileri atlayın

proje github'da:

Kullanımı:

1- bu dosyaları tek sayfalık uygulamanıza ekleyin:

  • core.js
  • scalyr.js
  • slyEvaluate.js
  • slyRepeat.js

2- Modül bağımlılığını ekleyin:

var app = angular.module("app", ['sly']);

3- ng tekrarını değiştirin

<tr sly-repeat="m in rows"> .....<tr>

Zevk almak!


4
Bu scalyr.js zaten diğer dosyaları içerir düşünüyorum. Çünkü derleme betiğinin sonucu.
dnocode

Scalyr kullanmaya çalıştım ama filtre çalışmıyor. <tr sly-repeat = "main.customers | filter: search_input | limitTo: 20">
aldesabido

Bu son derece yararlı. İstemcinin çok sayıda veri hücresini görmek istediği bir AngularJS 1.6 uygulamasında kullanıyorum (normal olarak disk belleği / azaltılmış veri öğeleri içeren formlar tasarlıyorum, ancak istemci aynı anda birçok veriyi karşılaştırmalı). Şimdiye kadar hücre ızgarası bu kütüphane nedeniyle kullanılamaz durumdan mükemmel inceliğe gitti. Ama bu lib AngularJS 1.2 gün içinde yazılmıştı, bu yüzden sorunları aramak için dikkatlice test edeceğim.
el ilanı

Şu anda söyleyebildiğim kadarıyla gatedScope.js dosyası (323 satır) AngularJS'nin daha güncel sürümlerinde çalıştırılabilmesi için doğrulanması gereken tek dosyadır. Bu çekme isteği dikkat çekicidir: github.com/karser/angular/commit/… . İmza rootScope'u günceller. $ New.
el ilanı

dört js dosyaları dahil ve kullanılan sly-repeatama hiçbir şey bana sonuçları hala yavaş ve tarayıcı gecikmeler de ihlal oluyor [Violation] 'setTimeout' handler took 54ms,[Violation] 'scroll' handler took 1298ms
Gaurav Aggarwal

15

Track by ve daha küçük döngüler gibi yukarıdaki ipuçlarının yanı sıra bu da bana çok yardımcı oldu

<span ng-bind="::stock.name"></span>

bu kod parçası yüklendikten sonra adı yazdırır ve bundan sonra izlemeyi bırakır. Benzer şekilde, ng tekrarları için,

<div ng-repeat="stock in ::ctrl.stocks">{{::stock.name}}</div>

ancak yalnızca AngularJS sürüm 1.3 ve üstü için çalışır. Gönderen http://www.befundoo.com/blog/optimizing-ng-repeat-in-angularjs/


::İfadenin yanı sıra tekrarda mı ihtiyacınız var ? Dokümanlar aksini söylüyor, ancak bunun işe yarayıp yaramadığını test etmenin yolundan emin değilim. docs.angularjs.org/guide/expression
Crhistian Ramirez

12

Performansı artırmak için "takip etme" işlevini kullanabilirsiniz:

<div ng-repeat="a in arr track by a.trackingKey">

Daha hızlı:

<div ng-repeat="a in arr">

ref: https://www.airpair.com/angularjs/posts/angularjs-performance-large-applications


1
Bu gerçekten performans için yardımcı olmaz. Bkz. Jsperf.com/ng-repeat-vs-ng-repeat-with-trace-by-id
ilter

track by ile her yeni veri aldığınızda dizi öğesini baştan izlemezsiniz. sonuç olarak bu performansı artırır.
user1920302

2
Bu sadece ng tekrarındaki veriler değiştiğinde kullanışlıdır. İlk yük için performans artışı sağlamayabilir.
Sumesh Kuttan

11

Tüm satırlarınız eşit yüksekliğe sahipse, sanallaştırma ng tekrarına kesinlikle göz atmalısınız: http://kamilkp.github.io/angular-vs-repeat/

Bu demo çok umut verici görünüyor (ve eylemsiz kaydırmayı destekliyor)


2
Mobil cihazlarda kaydırma performansı kabul edilemez (kaydırma etkinlikleri mobil iOS'ta tetiklenmez (yalnızca 8'den itibaren)
Johny

9

Kural No.1: Asla kullanıcının hiçbir şey beklemesine izin vermeyin.

10 saniyeye ihtiyaç duyan hayat büyüyen bir sayfanın, boş bir ekrandan önce 3 saniye beklemekten ve hepsini bir kerede almasından çok daha hızlı göründüğünü unutmayın.

Bu nedenle , sayfayı hızlı hale getirmek yerine , nihai sonuç daha yavaş olsa bile sayfanın hızlı görünmesine izin verin :

function applyItemlist(items){
    var item = items.shift();
    if(item){
        $timeout(function(){
            $scope.items.push(item);
            applyItemlist(items);
        }, 0); // <-- try a little gap of 10ms
    }
}

Yukarıdaki kod, listenin satır satır büyümesine izin veriyor ve her zaman aynı anda oluşturulmasından daha yavaş. Ancak kullanıcı için daha hızlı görünüyor.


html sayfasında bu işlevi nasıl kullanılır?
Antonis

9

Sanal kaydırma , büyük listeler ve büyük veri kümesiyle uğraşırken kaydırma performansını artırmanın başka bir yoludur.

Bunu uygulamanın bir yolu , bu Demo'da 50.000 öğe ile gösterildiği gibi Açısal Malzemeyi kullanmaktırmd-virtual-repeat

Doğrudan sanal tekrarın belgelerinden alınmıştır:

Sanal yineleme, kabı doldurmak ve kullanıcı kaydırdıkça geri dönüştürmek için yalnızca yeterli dom düğümünü işleyen ng-yinelemenin sınırlı bir alternatifidir.


2
Vay be, bence bu en ilginç cevap. Bu, açısalın eski sürümüyle çalışır mı? (ör. ver 1.2)
Thariq Nugrohotomo

2
@ThariqNugrohotomo Lütfen, Açısal Malzeme kullanmanın Açısal 1.3.x veya daha üstünün kullanılmasını gerektirdiğini unutmayın. Ayrıca destek için teşekkürler, gerçekten de sanal tekrardan çok şaşırıyorum ve zaten çok uzun bir sonuç listesi görüntüleyen bir mobil uygulamada kullanıyoruz.
Sarantis Tofas

6

Başka bir sürüm @Steffomio

Her öğeyi ayrı ayrı eklemek yerine, parçalar halinde öğeler ekleyebiliriz.

// chunks function from here: 
// http://stackoverflow.com/questions/8495687/split-array-into-chunks#11764168
var chunks = chunk(folders, 100);

//immediate display of our first set of items
$scope.items = chunks[0];

var delay = 100;
angular.forEach(chunks, function(value, index) {
    delay += 100;

    // skip the first chuck
    if( index > 0 ) {
        $timeout(function() {
            Array.prototype.push.apply($scope.items,value);
        }, delay);
    }       
});

İlginç fikir. Ben ~ 8000 öğeleri bir dizi üzerinde denedim ve başlangıçta sayfayı daha duyarlı hale getirirken, her yığın sonra daha az duyarlı oldu.
Paul Brannan

500'den fazla ürün aldıktan sonra bu benim app büyük bir sorun oldu. Bunun yerine sayfalama veya sonsuz yükleme öneririm.
joalcego

0

Bazen ne oldu, verileri birkaç ms'de sunucudan (veya arka uçtan) alıyorsunuz (örneğin, 100ms olduğunu düşünüyorum), ancak web sayfamızda görüntülenmesi daha uzun sürüyor (diyelim ki 900 ms sürüyor) Görüntüle).

Yani, burada olan şey 800 ms Sadece web sayfası oluşturmak için sürüyor.

Web uygulamamda yaptığım şey, sayfalandırma kullandım (veya sonsuz kaydırma kullanabilirsiniz) , veri listesini görüntülemek için da ). Diyelim ki 50 veri / sayfa gösteriyorum.

Bu yüzden bir kerede tüm verileri render yüklemeyeceğim, başlangıçta yüklediğim sadece 50 veri sadece 50 ms sürüyor (burada varsayıyorum).

bu nedenle toplam süre 900 ms'den 150 ms'ye düştü.

Umarım bu performansı artırmanıza yardımcı olur. Herşey gönlünce olsun


0
Created a directive (ng-repeat with lazy loading) 

sayfanın altına ulaştığında veri yükler ve önceden yüklenen verilerin yarısını kaldırır ve div'in üstüne ulaştığında veri (sayfa numarasına bağlı olarak) tekrar yüklenir. mevcut verilerin yarısı kaldırılır. bir seferde sadece sınırlı veri mevcuttur, bu da yükte tüm verileri oluşturmak yerine daha iyi performansa neden olabilir.

HTML KODU:

<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
    <script data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.20/angular.js" data-semver="1.3.20"></script>
    <script src="app.js"></script>
  </head>

  <body ng-controller="ListController">
  <div class="row customScroll" id="customTable" datafilter pagenumber="pageNumber" data="rowData" searchdata="searchdata" itemsPerPage="{{itemsPerPage}}"  totaldata="totalData"   selectedrow="onRowSelected(row,row.index)"  style="height:300px;overflow-y: auto;padding-top: 5px">

    <!--<div class="col-md-12 col-xs-12 col-sm-12 assign-list" ng-repeat="row in CRGC.rowData track by $index | orderBy:sortField:sortReverse | filter:searchFish">-->
    <div class="col-md-12 col-xs-12 col-sm-12 pdl0 assign-list" style="padding:10px" ng-repeat="row in rowData" ng-hide="row[CRGC.columns[0].id]=='' && row[CRGC.columns[1].id]==''">
        <!--col1-->

        <div ng-click ="onRowSelected(row,row.index)"> <span>{{row["sno"]}}</span> <span>{{row["id"]}}</span> <span>{{row["name"]}}</span></div>
      <!--   <div class="border_opacity"></div> -->
    </div>

</div>

  </body>

</html>

Açısal KOD:

var app = angular.module('plunker', []);
var x;
ListController.$inject = ['$scope', '$timeout', '$q', '$templateCache'];

function ListController($scope, $timeout, $q, $templateCache) {
  $scope.itemsPerPage = 40;
  $scope.lastPage = 0;
  $scope.maxPage = 100;
  $scope.data = [];
  $scope.pageNumber = 0;


  $scope.makeid = function() {
    var text = "";
    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

    for (var i = 0; i < 5; i++)
      text += possible.charAt(Math.floor(Math.random() * possible.length));

    return text;
  }


  $scope.DataFormFunction = function() {
      var arrayObj = [];
      for (var i = 0; i < $scope.itemsPerPage*$scope.maxPage; i++) {
          arrayObj.push({
              sno: i + 1,
              id: Math.random() * 100,
              name: $scope.makeid()
          });
      }
      $scope.totalData = arrayObj;
      $scope.totalData = $scope.totalData.filter(function(a,i){ a.index = i; return true; })
      $scope.rowData = $scope.totalData.slice(0, $scope.itemsperpage);
    }
  $scope.DataFormFunction();

  $scope.onRowSelected = function(row,index){
    console.log(row,index);
  }

}

angular.module('plunker').controller('ListController', ListController).directive('datafilter', function($compile) {
  return {
    restrict: 'EAC',
    scope: {
      data: '=',
      totalData: '=totaldata',
      pageNumber: '=pagenumber',
      searchdata: '=',
      defaultinput: '=',
      selectedrow: '&',
      filterflag: '=',
      totalFilterData: '='
    },
    link: function(scope, elem, attr) {
      //scope.pageNumber = 0;
      var tempData = angular.copy(scope.totalData);
      scope.totalPageLength = Math.ceil(scope.totalData.length / +attr.itemsperpage);
      console.log(scope.totalData);
      scope.data = scope.totalData.slice(0, attr.itemsperpage);
      elem.on('scroll', function(event) {
        event.preventDefault();
      //  var scrollHeight = angular.element('#customTable').scrollTop();
      var scrollHeight = document.getElementById("customTable").scrollTop
        /*if(scope.filterflag && scope.pageNumber != 0){
        scope.data = scope.totalFilterData;
        scope.pageNumber = 0;
        angular.element('#customTable').scrollTop(0);
        }*/
        if (scrollHeight < 100) {
          if (!scope.filterflag) {
            scope.scrollUp();
          }
        }
        if (angular.element(this).scrollTop() + angular.element(this).innerHeight() >= angular.element(this)[0].scrollHeight) {
          console.log("scroll bottom reached");
          if (!scope.filterflag) {
            scope.scrollDown();
          }
        }
        scope.$apply(scope.data);

      });

      /*
       * Scroll down data append function
       */
      scope.scrollDown = function() {
          if (scope.defaultinput == undefined || scope.defaultinput == "") { //filter data append condition on scroll
            scope.totalDataCompare = scope.totalData;
          } else {
            scope.totalDataCompare = scope.totalFilterData;
          }
          scope.totalPageLength = Math.ceil(scope.totalDataCompare.length / +attr.itemsperpage);
          if (scope.pageNumber < scope.totalPageLength - 1) {
            scope.pageNumber++;
            scope.lastaddedData = scope.totalDataCompare.slice(scope.pageNumber * attr.itemsperpage, (+attr.itemsperpage) + (+scope.pageNumber * attr.itemsperpage));
            scope.data = scope.totalDataCompare.slice(scope.pageNumber * attr.itemsperpage - 0.5 * (+attr.itemsperpage), scope.pageNumber * attr.itemsperpage);
            scope.data = scope.data.concat(scope.lastaddedData);
            scope.$apply(scope.data);
            if (scope.pageNumber < scope.totalPageLength) {
              var divHeight = $('.assign-list').outerHeight();
              if (!scope.moveToPositionFlag) {
                angular.element('#customTable').scrollTop(divHeight * 0.5 * (+attr.itemsperpage));
              } else {
                scope.moveToPositionFlag = false;
              }
            }


          }
        }
        /*
         * Scroll up data append function
         */
      scope.scrollUp = function() {
          if (scope.defaultinput == undefined || scope.defaultinput == "") { //filter data append condition on scroll
            scope.totalDataCompare = scope.totalData;
          } else {
            scope.totalDataCompare = scope.totalFilterData;
          }
          scope.totalPageLength = Math.ceil(scope.totalDataCompare.length / +attr.itemsperpage);
          if (scope.pageNumber > 0) {
            this.positionData = scope.data[0];
            scope.data = scope.totalDataCompare.slice(scope.pageNumber * attr.itemsperpage - 0.5 * (+attr.itemsperpage), scope.pageNumber * attr.itemsperpage);
            var position = +attr.itemsperpage * scope.pageNumber - 1.5 * (+attr.itemsperpage);
            if (position < 0) {
              position = 0;
            }
            scope.TopAddData = scope.totalDataCompare.slice(position, (+attr.itemsperpage) + position);
            scope.pageNumber--;
            var divHeight = $('.assign-list').outerHeight();
            if (position != 0) {
              scope.data = scope.TopAddData.concat(scope.data);
              scope.$apply(scope.data);
              angular.element('#customTable').scrollTop(divHeight * 1 * (+attr.itemsperpage));
            } else {
              scope.data = scope.TopAddData;
              scope.$apply(scope.data);
              angular.element('#customTable').scrollTop(divHeight * 0.5 * (+attr.itemsperpage));
            }
          }
        }
    }
  };
});

Direktif ile demo

Another Solution: If you using UI-grid in the project then  same implementation is there in UI grid with infinite-scroll.

Bölümün yüksekliğine bağlı olarak verileri yükler ve kaydırma üzerine yeni veriler eklenir ve önceki veriler kaldırılır.

HTML Kodu:

<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <link rel="stylesheet" href="https://cdn.rawgit.com/angular-ui/bower-ui-grid/master/ui-grid.min.css" type="text/css" />
    <script data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.20/angular.js" data-semver="1.3.20"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-grid/4.0.6/ui-grid.js"></script>
    <script src="app.js"></script>
  </head>

  <body ng-controller="ListController">
     <div class="input-group" style="margin-bottom: 15px">
      <div class="input-group-btn">
        <button class='btn btn-primary' ng-click="resetList()">RESET</button>
      </div>
      <input class="form-control" ng-model="search" ng-change="abc()">
    </div>

    <div data-ui-grid="gridOptions" class="grid" ui-grid-selection  data-ui-grid-infinite-scroll style="height :400px"></div>

    <button ng-click="getProductList()">Submit</button>
  </body>

</html>

Açısal Kod:

var app = angular.module('plunker', ['ui.grid', 'ui.grid.infiniteScroll', 'ui.grid.selection']);
var x;
angular.module('plunker').controller('ListController', ListController);
ListController.$inject = ['$scope', '$timeout', '$q', '$templateCache'];

function ListController($scope, $timeout, $q, $templateCache) {
    $scope.itemsPerPage = 200;
    $scope.lastPage = 0;
    $scope.maxPage = 5;
    $scope.data = [];

    var request = {
        "startAt": "1",
        "noOfRecords": $scope.itemsPerPage
    };
    $templateCache.put('ui-grid/selectionRowHeaderButtons',
        "<div class=\"ui-grid-selection-row-header-buttons \" ng-class=\"{'ui-grid-row-selected': row.isSelected}\" ><input style=\"margin: 0; vertical-align: middle\" type=\"checkbox\" ng-model=\"row.isSelected\" ng-click=\"row.isSelected=!row.isSelected;selectButtonClick(row, $event)\">&nbsp;</div>"
    );


    $templateCache.put('ui-grid/selectionSelectAllButtons',
        "<div class=\"ui-grid-selection-row-header-buttons \" ng-class=\"{'ui-grid-all-selected': grid.selection.selectAll}\" ng-if=\"grid.options.enableSelectAll\"><input style=\"margin: 0; vertical-align: middle\" type=\"checkbox\" ng-model=\"grid.selection.selectAll\" ng-click=\"grid.selection.selectAll=!grid.selection.selectAll;headerButtonClick($event)\"></div>"
    );

    $scope.gridOptions = {
        infiniteScrollDown: true,
        enableSorting: false,
        enableRowSelection: true,
        enableSelectAll: true,
        //enableFullRowSelection: true,
        columnDefs: [{
            field: 'sno',
            name: 'sno'
        }, {
            field: 'id',
            name: 'ID'
        }, {
            field: 'name',
            name: 'My Name'
        }],
        data: 'data',
        onRegisterApi: function(gridApi) {
            gridApi.infiniteScroll.on.needLoadMoreData($scope, $scope.loadMoreData);
            $scope.gridApi = gridApi;
        }
    };
    $scope.gridOptions.multiSelect = true;
    $scope.makeid = function() {
        var text = "";
        var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

        for (var i = 0; i < 5; i++)
            text += possible.charAt(Math.floor(Math.random() * possible.length));

        return text;
    }
    $scope.abc = function() {
        var a = $scope.search;
        x = $scope.searchData;
        $scope.data = x.filter(function(arr, y) {
            return arr.name.indexOf(a) > -1
        })
        console.log($scope.data);
        if ($scope.gridApi.grid.selection.selectAll)
            $timeout(function() {
                $scope.gridApi.selection.selectAllRows();
            }, 100);
    }


    $scope.loadMoreData = function() {
        var promise = $q.defer();
        if ($scope.lastPage < $scope.maxPage) {
            $timeout(function() {
                var arrayObj = [];
                for (var i = 0; i < $scope.itemsPerPage; i++) {
                    arrayObj.push({
                        sno: i + 1,
                        id: Math.random() * 100,
                        name: $scope.makeid()
                    });
                }

                if (!$scope.search) {
                    $scope.lastPage++;
                    $scope.data = $scope.data.concat(arrayObj);
                    $scope.gridApi.infiniteScroll.dataLoaded();
                    console.log($scope.data);
                    $scope.searchData = $scope.data;
                    // $scope.data = $scope.searchData;
                    promise.resolve();
                    if ($scope.gridApi.grid.selection.selectAll)
                        $timeout(function() {
                            $scope.gridApi.selection.selectAllRows();
                        }, 100);
                }


            }, Math.random() * 1000);
        } else {
            $scope.gridApi.infiniteScroll.dataLoaded();
            promise.resolve();
        }
        return promise.promise;
    };

    $scope.loadMoreData();

    $scope.getProductList = function() {

        if ($scope.gridApi.selection.getSelectedRows().length > 0) {
            $scope.gridOptions.data = $scope.resultSimulatedData;
            $scope.mySelectedRows = $scope.gridApi.selection.getSelectedRows(); //<--Property undefined error here
            console.log($scope.mySelectedRows);
            //alert('Selected Row: ' + $scope.mySelectedRows[0].id + ', ' + $scope.mySelectedRows[0].name + '.');
        } else {
            alert('Select a row first');
        }
    }
    $scope.getSelectedRows = function() {
        $scope.mySelectedRows = $scope.gridApi.selection.getSelectedRows();
    }
    $scope.headerButtonClick = function() {

        $scope.selectAll = $scope.grid.selection.selectAll;

    }
}

Sonsuz kaydırma Demo ile UI ızgarası ile demo


Bir çözümün bağlantısı hoş karşılanır, ancak lütfen cevabınızın onsuz faydalı olduğundan emin olun: bağlantınızın çevresine bağlam ekleyin, böylece diğer kullanıcılarınız ne olduğu ve neden orada olduğu hakkında bir fikir edinebilir, ardından sayfanın en alakalı bölümünü alıntılayabilirsiniz ' hedef sayfanın kullanılamaması durumunda bağlantı kuruluyor. Bir bağlantıdan biraz daha fazlası olan yanıtlar silinebilir .
Sᴀᴍ Onᴇᴌᴀ

-2

büyük veri kümesi ve çoklu değer açılır menüsü için kullanmak ng-optionsdaha iyidir ng-repeat.

ng-repeatyavaştır çünkü tüm gelen değerlerin üzerinden geçer, ancak ng-optionsyalnızca seçme seçeneğine görüntülenir.

ng-options='state.StateCode as state.StateName for state in States'>

çok daha hızlı

<option ng-repeat="state in States" value="{{state.StateCode}}">
    {{state.StateName }}
</option>

Ng-options'un performansını kontrol ettiniz mi? Kodumu optimize etmeye çalışıyorum ve yardımcı olmadı. Hız ng-tekrar ile aynıdır. -1
Icet

sadece seçme için çalışır, ng-repeat çok daha güçlüdür. Bununla birlikte ng-Options'ın ng-tekrarından çok daha hızlı olduğu doğrudur. AngularJs belgeleri farklılıklar için 2000 maddeden bahsediyor: docs.angularjs.org/api/ng/directive/select
kaiser
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.