Pagination - DevNatan/inventory-framework GitHub Wiki

IF pagination allows you to display a large amount of data in an inventory by separating it into pages.

Pagination is a state value, that is, you have a paging value for each host, a host can be anything that implements StateHost like for example: a context. Learn more about State Management.

final class MyAbsolutelyInsanePaginatedView extends View {

    private final PaginationState paginationState = paginationState(sourceProvider, itemFactory);

}

To create a pagination state you have two essential parameters:

  1. sourceProvider will be used to define the pagination data, e.g.: a list of things.
  2. itemFactory will be used to create the items that will be displayed in the view for each paginated element, e.g.: a head of a player.

Composition

In the example below, our data to be paginated is a list of player names that we provide in the sourceProvider parameter, and for each name we will display a head provided by the itemFactory parameter.

Preview
private final PaginationState paginationState = paginationState(
    Arrays.asList("Notch", "DevNatan", "Annie are you ok?"),
    (item, $) -> item.withItem(new ItemStack(PLAYER_HEAD))
);


The second parameter, itemFactory is a BiConsumer<T, V> being T what you will use to define your item, it is the same type used to create the items in the slot, layoutSlot, etc., and V is the element being paginated, in our case a String that's the player name.

Preview
private final PaginationState paginationState = paginationState(
    Arrays.asList("Notch", "DevNatan", "Annie are you ok?"),
    (item, playerName) -> item.withItem(createHead(playerName))
);

private ItemStack createHead(String name) { ... }

TIP: Create a function for creating items that will be paginated to improve readability.

Working with layouts

IF adapts the pagination automatically if there is a defined layout.
Read about how layouts interact with other components.

Look how this code similar to the previous examples but with more items behaves with and without layout.

private final PaginationState paginationState = paginationState(
    Arrays.asList("Notch", "DevNatan", "Steve", "Github", "SpiderMan"),
    (item, playerName) -> item.withItem(createHead(playerName))
);
No layout With layout
Preview Preview

Dive into Pagination

Like other states, PaginationState exposes a specific type of value called Pagination, which is where the paging data of a context is stored.

final Pagination pagination = paginationState.get(context);

It contains several functions such as the number and index of the current page, next and previous pages, pagination data, navigation, among others. Dive into this class to discover the possibilities of what to do with pagination for a context.

Navigation

Browsing is no secret and there are some very explicitly named functions for it.

  • back() Return to previous page if available.
  • advance() Advances to the next page if any.
  • switchTo(n) Jumps to a specific page index.
Replicating version 2 behavior

In version 2 and earlier there were specific functions to create navigation for pagination like < and > in the layout and other predefined things, that doesn't exist anymore.

If you want to replicate the behavior of previous versions you can use layoutSlot.
< will be the "navigate backwards" item and > the "navigate forward" one

final class OctopusView extends View {

    private final PaginationState paginationState = paginationState(...);

    @Override
    public void onInit(ViewConfigBuilder config) {
        config.size(3).layout(
	     " OOOOOOO ",
	     " OOOOOOO ",
	     "   < >    "
	);
    }

    @Override
    public void onFirstRender(RenderContext render) {
        final Pagination pagination = paginationState.get(render);

        render.layoutSlot('<').onClick(pagination::back);
        render.layoutSlot('>').onClick(pagination::advance);
    }
}

Dynamic Source Provider

In the Composition topic I showed you a pagination with a list of names, a static list of player names but we know that in the real world we have several types of data besides static like dynamic. Inventory Framework allows you to use dynamic data, that is, the data is not defined statically but taken from a continuous source.

Straight to the point, to create dynamic paging just provide a data factory instead of the data directly, that is:
instead of passing a List<...>, provide Supplier<List<...>> , Factory<List<...>>**

Let's see a real world example of dynamic pagination data

This is a view that displays the list of players online on the server.
Obviously players join and leave the server constantly so we couldn't use static data.

Pay close attention to the minimal difference between static and dynamic pagination data.

Static

This data will be the same data that will be used throughout the life cycle of that state, if players leave and enter the server nothing will change, as it is the data provided from a moment in time, that is, it will be the same data throughout life.

private final PaginationState paginationState = paginationState(
    Bukkit.getOnlinePlayers(),
    (item, value) ->
);
Dynamic
private final PaginationState paginationState = paginationState(
    () -> Bukkit.getOnlinePlayers(),
    (item, value) ->
);

Handling Page Switch

TBD

Next Topics

Learn how to simplify, shorten and improve interview navigation using the History feature.

⚠️ **GitHub.com Fallback** ⚠️