angular-ui/ui-scroll

Many ng-scroll on the page with different datasources

villian opened this issue · 4 comments

Hello,

Thanks for a great package.

I'm struggling with making many ng-scoll items on the page, they are actually in ng-repeat and have different datasources

Datasources are the problem, how to make dynamic datasets and wrap in datasources? How can I pass params from angular view from rendering to the datasource to provide data?

so I need something like this - https://plnkr.co/edit/JjAiw3zvG4uIWGNjLUU7?preview

but with dynamic datasource for each ng-scroll

dhilt commented

@villian If you need 2 different Datasources for two different views, you may just define 2 ds objects:

<tr ui-scroll="item in datasource" adapter="adapter">
...
<tr ui-scroll="item in datasource2" adapter="adapter2">
$scope.datasource = { get: /* implementation of ds1 */ };
$scope.datasource2 = { get: /* implementation of ds2 */  };

But if you need to have multiple datasources under a single umbrella, the following approach might be useful. Basically, if you can guarantee indexes consistency across the datasources, you may provide the replacement of the datasource.get method body in runtime:

let myDynamicDatasource = (i, c, s) => s([]); // stub ds.get

$scope.datasource = {
  get: (index, count, success) =>
    myDynamicDatasource(index, count, success)
};

// data is new array of items we want to loop through with ui-scroll
$scope.onDatasourceChanged = (data) =>
  myDynamicDatasource = (index, count, success) =>
    success(data.slice(index, index + count));

But if each ds has its own indexes flow not correlating with others, then I would advise to clean up the internal state via Adapter.reload API:

$scope.onDatasourceChanged = (data, indexToReload) => {
  myDynamicDatasource = (index, count, success) =>
    success(data.slice(index, index + count));
  $scope.adapter.reload(indexToReload);
}

Thanks, for the response! This is what we have:

<li ng-repeat="product in products">
<ul ng-if="items[product.id]">
<li ui-scroll="item in datasource">
</li>
</ul>

I have to pass productId into datasource somehow and datasource should be unique for

do we need an array with all items and then manage it via indexes? any idea?

dhilt commented

@villian Well I think I got the issue. Basically, datasource is an object with "get" field which should exist on $scope during render, and if you know the products array length, you may arrange appropriate number of datasources pushed in a single map-object with keys corresponded to the list of product ids:

<li ng-repeat="product in products">
  <ul ng-if="items[product.id]">
    <li ui-scroll="item in datasources[product.id]">
    </li>
  </ul>
</li>

Below is the draft implementation of the datasource-product map.

const getDataByProduct = (product, index, count, callback) => {
  // the logic of this method might be dynamic/async
  // anyway here you have all the data to provide appropriate potion of data
  const data = $scope.items[product.id] || [];
  callback(data.slice(index, index + count));
};

const createDatasource = (product) => ({
  get: (index, count, success) =>
    getDataByProduct(product, index, count, success)
});

$scope.datasources = $scope.products.reduce((acc, product) => ({
  ...acc,
  [product.id]: createDatasource(product)
}), {});