Infinite scroll with nested array (Divider list)


#1

Hi,
I’m trying to apply infinite scroll on a rather complex array.
It looks like :

var chapters = [{
	id: 1,
	name: 'Foo',
	analyses: [{
		id: 1,
		name: 'Bar'
	}, {...}, {...}]
}, {...}, {...}];

If I render the entire array like this, everything is fine :

<div class="list">
    <div ng-repeat-start="chapter in chapters track by chapter.id" ng-if="chapter.analyses.length > 0" class="item item-divider">{{chapter.name}}</div>
    <a ng-repeat="analysis in chapter.analyses track by analysis.id | filter:search" ng-repeat-end ng-click="viewAnalysis({{analysis.id}})" class="item">
        {{analysis.name}}
    </a>
</div>
<ion-infinite-scroll on-infinite="fetchAnalyses()" distance="10%"></ion-infinite-scroll>

Now I’m stuck with the fetchAnalyses() function. I don’t know how to slice my array by the analyses and keeping the current structure.
For example, if my array structure is : [Parent => [Child, Child, Child], Parent => [Child, Child]], and I decide to get 2 items with fetchAnalyses, the sliced array will be : [Parent => [Child, Child]], then the next call : [Parent => [Child, Child, Child], Parent => [Child]].

Any idea ?


#2

I resolved my issue by “flattening” my array :

for (var i in chapters) {
                var chapter= chapters[i];
                var analyses = chapter.analyses;
                delete chapter.analyses;
                chapter.divider = true;
                dataSrc = dataSrc.concat(chapter, analyses);
            }

Everything works now, by fetching the elements like this :

var requestCounter = 0;
    var requestLimit = 15;
    var dataSrc = [];
    $scope.datas = [];
    $scope.hasMoreData = true;
$scope.fetchData = function() {
        requestCounter++;
        var start = (requestCounter - 1) * requestLimit;
        var datas = dataSrc.slice(start, start + requestLimit);
        $scope.datas = $scope.datas.concat(datas);
        if (((requestCounter - 1) * requestLimit) > dataSrc.length)
            $scope.hasMoreData = false;
        $scope.$broadcast('scroll.infiniteScrollComplete');
    };

Then in the template :

<div class="list">
            <div ng-repeat-start="data in datas" ng-if="data.divider" class="item item-divider">{{data.name}}</div>
            <a ng-repeat-end ng-if="!data.divider" ng-click="viewAnalysis({{data.id}})" class="item">
                {{data.name}}
            </a>
        </div> 

Now I have a bonus question :slight_smile:
How can I filter the entire dataSrc array and when the user clears the search input, fallback to the partially loaded list ?

EDIT :
I came up with this solution to filter an infinite list :

var partialData = [];
$scope.activeSearch = false;
$scope.filterData = function(input) {
            if (!$scope.activeSearch) {
                $scope.activeSearch = true;
                partialData = $scope.datas;
            }
            if (input.length === 0) {
                $scope.activeSearch = false;
                $scope.datas = partialData;
                partialData = [];
            } else {
                $scope.datas = filterFilter(dataSrc, {libelle_analyte: input});
            }
        };

Then in the template I added a activeSearch condition :

<ion-infinite-scroll on-infinite="fetchData()" ng-if="!activeSearch && hasMoreData" distance="1%"></ion-infinite-scroll>

If anyone want to improve this solution, I’ll be happy. :smiley: