Search code examples
phpyiipaginationyii-components

Effective pagination of decreasing results


I'm working for a client who asks me to prepare a module for its website (written using Yii) with the following features:

  • It shows 3 elements from a mysql_result, starting from offset=0.
  • The user can click on any of them to mark them as "read". That makes the desired item to disappear and to appear what would be the following item. That is, if you are showing items 3 4 5 and you click on 4, that item would disappear and appear the number 6, meaning the result would be 3 5 6.
  • The elements being shown are partial views and the button that "deletes" the item is a widget within each partial view.
  • The user can move through the list of items using some << and >> arrows to go back and forth the result.
  • One of the options the client gave to me was to show a list of pages ( 1 | 2 | 3 | 4... and so), but deleting items means the number of pages will decrease at some time in the future, plus if the amount is pretty big, I would need something more flexible such as only showing the current and other 4 pages at most. Another option is to keep the << and >> arrows.
  • I've tried to convince the client that pagination and a "live list" is a pretty bad idea, but he rejected the idea to limit the visualization to only the first 3 items (keeping in mind that eventually you will delete them and thus will be able to see the following items).

I'm developing it using Yii, MySQL and jQuery, and I'm not able to use CPagination because of this living list. I'm not asking the code, just some guidelines because I got lost the third time I tried doing it.

Some basics about the system:

  • I got a controller which loads the first 3 items of this module.
  • I got some actions in this controller that fetches the next item within a page (which may not be the same of the current object, though. One of my problems resides here), and the full page.
  • Each item is able to mark itself as "read", which will make the item not appearing the next time you fetch some results.
  • Every 1 second I check for items that have been marked as read, remove from DOM and append some new items using the action I defined in the second bullet.
  • Every time the user hits the << or >>, I reload the previous/next page (That would not be a problem apparently. If you're in the last page and there aren't more items to add, you just remain there. However if you empty the page, I don't have any method to detect that and scroll one page back).

As you may see, this headache would be easier without the pagination buttons, but the client obligues me to put them. What would you do guys? Thanks in advance

EDIT: The client decided to get the results in a random flavor. There is no more pagination, so the problem has disappeared. The @thaddeusmt answer may not have helped me really much, but I'll give it as valid, as it might be plenty useful for other people with similar problems than mine. Cheers


Solution

  • It seems to me like the CGridView or CListView should basically do this automatically. They support AJAX updating/paging out-of-the-box.

    I assume that you have an AJAX action that like "actionMarkRead()" which you are calling when the user clicks. I assume that this sets some database field somewhere saying that the user has "Read" that item. To make this work with the CListView, just make sure that the CDataProvider has a condition which checks that "read" field (might have to JOIN a table, I don't know what your DB looks like). Then, when the list reloads via AJAX, it will have the correct # of pages to represent the smaller number of pages the CDataProvier query is returning.

    I just tested this and it works!

    The way I tested it is I set up a CGridView with 'ajaxUpdate'=>true,. Then in my CDataProvider I set 'pagination'=>1 to make it easy to test. Then I used the default AJAX actionDelete in my Controller to delete the items. Every time I deleted an item via that AJAX action link in the CGridView, the grid refreshed via AJAX and page count shrunk by 1. Seems to work like a charm!

    Cheers and good luck!