prikhi / paginate / Paginate

Paginate is used for querying & paginating API responses. Paginate will handle fetching new pages of data, and caches already fetched data.

TODO: Eventually:

Model


type Paginated a b c

The Paginated type is responsible for storing the fetched items, current page number, total count, and additional data to pass to the fetch command..

The a type refers to the data that is paginated, b refers to any additional data you need to make the API request, and c is any additional data you want to pull out of the API response.

initial : Config a b c -> b -> Basics.Int -> Basics.Int -> ( Paginated a b c, Platform.Cmd.Cmd (Msg a c) )

Get an initial Pagination & Fetch Commands from a Config, list of Filters, & Page Number.

Config


type Config a b c

The Config type is used to build a Fetch Request, given the Paginated's Request Data, a Page Number, & the Items per Page.


type alias FetchResponse a c =
{ items : List a
, totalCount : Basics.Int
, extraData : Maybe c 
}

The result type of a Paginated Fetch Request. At the minimum, your API needs to return the items & a total count of all items.

If any additional data is returned that you would like to have access to, you can decode it to the extraData field and use getResponseData to pull it out of a Paginated.

makeConfig : (b -> Basics.Int -> Basics.Int -> Platform.Cmd.Cmd (RemoteData.WebData (FetchResponse a c))) -> Config a b c

Make a Config from a function that takes a list of Parameters & a Page Number.

Retrieving Data

getCurrent : Paginated a b c -> List a

Get the current list of items.

getPage : Paginated a b c -> Basics.Int

Get the current page number.

getPerPage : Paginated a b c -> Basics.Int

Get the number of items to show per page.

getTotalPages : Paginated a b c -> Basics.Int

Get the total number of pages.

getTotalItems : Paginated a b c -> Basics.Int

Get the total item count.

getError : Paginated a b c -> Maybe Http.Error

Return the current page's fetch request's error if it has one.

getRequestData : Paginated a b c -> b

Return the Extra Request Data for the current Paginated.

getResponseData : Paginated a b c -> Maybe c

Return any Extra Response Data for the current Paginated.

getRemoteData : Paginated a b c -> RemoteData.WebData (List a)

Return the raw WebData for the current page.

Rendering

getPagerSections : Basics.Int -> Basics.Int -> Paginated a b c -> List (List ( Basics.Int, Basics.Bool ))

Generate sections of pages to show for a Pager. Depending on the current page & total number of pages, the sections may either be a single section, a beginning & end section, or a beginning, middle, & end section.

Each section's page is a tuple of (pageNumber, isCurrentPage).

The sections are defined by the initial arguments, the first is the number of pages to show at the end sections, while the second is the number of pages to show around the current page if it is in the middle section.

Some example of Pagers generated with 2 end & middle pages, with the current page marked by *:

*1*|2|3|4|5|6

*1*|2|3|4|5|...|49|50

1|2|3|4|*5*|...|49|50

1|2|...|4|5|*6*|7|8|...|49|50

1|2|...|9|10|*11*|12|13|...|49|50

1|2|...|*46*|47|48|49|50

No split is made if there are not enough pages to show a middle section. When at an end section, enough pages are shown that there must be something hidden before splitting off the middle section.

bootstrapPager : (Basics.Int -> List (Html.Attribute msg)) -> Basics.Int -> Basics.Int -> Paginated a b c -> List (Html msg)

Render a split Pager with the standard Bootstrap4 classes.

It takes a function that takes a page number & generates attributes for an item's a element, the number of pages to show at the ends of the pagination, the number of middle pages to show in the middles of the pagination, and a pagination.

It will split out a list of li elements for each page that should be shown, with disabled dots(...) between each section. A list is returned so that you can add previous/next buttons if you want them.

See the docs for getPagerSections to see how the splitting works.

Querying Status

isLoading : Paginated a b c -> Basics.Bool

Is the current page's fetch request still loading?

hasNone : Paginated a b c -> Basics.Bool

Did the current page load successfully but return no items?

isFirst : Paginated a b c -> Basics.Bool

Is the current page the first page?

isLast : Paginated a b c -> Basics.Bool

Is the current page the last page?

hasPrevious : Paginated a b c -> Basics.Bool

Are there page's before the current one?

hasNext : Paginated a b c -> Basics.Bool

Are there page's after the current one?

Modifying Pagination

moveNext : Config a b c -> Paginated a b c -> ( Paginated a b c, Platform.Cmd.Cmd (Msg a c) )

Move to the next page. TODO: re-implement as call to jumpTo?

movePrevious : Config a b c -> Paginated a b c -> ( Paginated a b c, Platform.Cmd.Cmd (Msg a c) )

Move to the previous page. TODO: re-implement as call to jumpTo?

jumpTo : Config a b c -> Basics.Int -> Paginated a b c -> ( Paginated a b c, Platform.Cmd.Cmd (Msg a c) )

Move to a specific page.

updateData : Config a b c -> b -> Paginated a b c -> ( Paginated a b c, Platform.Cmd.Cmd (Msg a c) )

Replace the current Extra Request Data, jumping to page 1 & performing new fetch requests. Does nothing if the Data is equal to existing Data.

updateAndResetData : Config a b c -> b -> Paginated a b c -> ( Paginated a b c, Platform.Cmd.Cmd (Msg a c) )

Similar to the updateData function, but this will also reset the ResponseData.

Which you should pick depends on how the new request data affects your response data. E.g., if the slug of the pagination container changes, you should reset the response data as well, but if you're only changing the sorting order of the results, you can just use the updateData function.

updatePerPage : Config a b c -> Basics.Int -> Paginated a b c -> ( Paginated a b c, Platform.Cmd.Cmd (Msg a c) )

Update the items per page, jumping to page 1 & performing new fetch requests. Does nothing if the new value is the same as the current items per page.

Updating / Messages


type Msg a c

Wrap an Http Response for a Page, to be handled in the update function.

update : Config a b c -> Msg a c -> Paginated a b c -> ( Paginated a b c, Platform.Cmd.Cmd (Msg a c) )

Update the Paginated Model on Fetch Completion.

If the Page Number of the Returned Model is Different than the Given Model, We Were On a Page That Didn't Exist, So We Changed to the Last Page.

You Should Handle this Special Case in your Update Function, so that You can Modify the Page URL.