'Yii2 ArrayDataProvider does not show already paginated data
I have an issue with ArrayDataProvider object that Yii2 provides. I have a huge API call that returns more than 7k items (this is a problem because obtaining all items takes a long time). I realized that I can tell the API to paginate for me so I was trying to implement the already paginated data into an ArrayDataProvider but only works in page 1, when I ask for page 2 I see that API returns the next 50 items but in my view the GridView object does not show anything.
An example:
$dataProvider = new ArrayDataProvider([
'key' => 'id',
'allModels' => $items,
'totalCount' => self::GetNumOfItems(),
'sort' => [
'attributes' => ['id', 'name', 'email'],
],
'pagination' => [
'pageSize' => 50,
],
]);
I ask for the total amount of items to properly display the paginator. If I ask for page 1 all is working fine but if a change to page 2 or whatever the gridview is showing no items. I suspect that is related with the already paginated data but, is there a way to make this work?
Solution 1:[1]
ArrayDataProvider
paginates through all elements in $allModels
. So if you have 50 items per page, second page will show models 51-100. If you already have paginated data and $items
contains only 50 elements from second page, ArrayDataProvider
will still search for models 51-100, which do not exist, so you get empty page.
In your case you should probably not use ArrayDataProvider
and write your own data provider which will work like a proxy to API. ArrayDataProvider
still needs all models to perform sorting or filtering, so either you will fetch all 7k items from API and allow to handle filtering and sorting at ArrayDataProvider
level, or filtering and sorting should be done at API level and none of existing data provider from framework core will fit your needs.
You may search for extension with something like ProxyDataProvider
, but it may be hard to find something that will match your API.
Solution 2:[2]
ArrayDataProvider has a "prepareModels" method that forms an array of data. Inside the method, there is an array_slice() function that selects an array slice based on the page number. That's why the gridview doesn't show on other pages any items. Image "prepareModels" method
You can inherit from ArrayDataProvider, override the "prepareModels" method and remove the "array_slice" function.
For example, my ApiArrayDataProvider and SearchModel
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | rob006 |
Solution 2 | Sergey |