mydomain
No ADS
No ADS

FlutterArtist BlockNumberPagination Ex1

  1. Structure of the example
  2. Teacher14aShelf
  3. DebugBlockStateView
  4. BlockNumberPagination
Pagination is a crucial feature for enhancing user experience by breaking down large content into smaller parts. This technique makes content more manageable and navigable while preventing users from being overwhelmed by too much information displayed at once.
FlutterArtist hỗ trợ cả hai phương pháp phân trang phổ biến nhất hiện nay:
  • Numbered Pagination: Divides content into numbered pages. Users can select a specific page index to view the corresponding content. This technique is standard for Web applications.
  • Infinite Scroll: Loads and displays a portion of content, with subsequent parts automatically appended as the user scrolls to the bottom. This technique is typically preferred for Mobile applications.
In this article, we will demonstrate an example using the first pagination technique mentioned above with BlockNumberPagination, a built-in widget in FlutterArtist.
Note regarding the combination with Filter and States:
In this example, we will highlight the automatic page index management mechanism. To ensure the accuracy of the displayed data, the page index is automatically reset to 1 by default if one of the following situations occurs:
  • Filter Criteria change.
  • The currentItem of the parent Block changes (in Master-Detail scenarios).
  • Server-side Sort Criteria change.
No ADS
Why is this Reset crucial?
  • Avoiding Orphaned Data (Tránh dữ liệu "mồ côi"): Nếu bạn đang ở trang 10 của danh sách 1000 bản ghi, nhưng sau khi lọc chỉ còn 5 bản ghi, việc giữ nguyên trang 10 sẽ khiến màn hình bị trắng (không có dữ liệu).
  • Consistency in Sorting: When switching from "Oldest" to "Newest" sorting, the dataset for page 1 changes entirely. Users must be brought back to the first page to see the most relevant records according to the new criteria.
  • Master-Detail Synchronization: When you select a different Order in the parent Block, the detail list in the child Block must restart from page 1 for that specific new order.
Chú ý: Bài viết hiện tại mà bạn đang đọc có liên quan tới việc sử dụng bộ lọc trong FlutterArtist, vì vậy bạn nên tìm hiểu các ví dụ liên quan tới bộ lọc trước khi tiếp tục với bài viết này.
  • FlutterArtist Filter - Ví dụ 1
  • FlutterArtist FilterInput - Ví dụ 1
  • FlutterArtist FilterModel MultiOptFilterCriterion - Ví dụ 1
Các ví dụ liên quan:
  • Flutter GridView with custom SliverGridDelegate

1. Structure of the example

Interface components:

2. Teacher14aShelf

The structure of Teacher14aShelf is quite simple, consisting of one FilterModel and one Block.
teacher14a_shelf.dart
class Teacher14aShelf extends Shelf {
  @override
  ShelfStructure defineShelfStructure() {
    return ShelfStructure(
      filterModels: {
        Teacher14aFilterModel.filterName: Teacher14aFilterModel(),
      },
      blocks: [
        Teacher14aBlock(
          name: Teacher14aBlock.blkName,
          description: null,
          config: BlockConfig(
            pageable: Pageable(pageSize: 10),
          ),
          filterModelName: Teacher14aFilterModel.filterName,
          formModel: null,
          childBlocks: [],
        ),
      ],
    );
  }

  Teacher14aBlock findTeacher14aBlock() {
    return findBlock(Teacher14aBlock.blkName) as Teacher14aBlock;
  }

  Teacher14aFilterModel findTeacher14aFilterModel() {
    return findFilterModel(Teacher14aFilterModel.filterName)
        as Teacher14aFilterModel;
  }
}
The pageable parameter of the Block allows you to specify the maximum number of ITEM(s) to be displayed on each page.
Teacher14aBlock(
  name: Teacher14aBlock.blkName,
  description: null,
  config: BlockConfig(
    pageable: Pageable(pageSize: 10),
  ),
  filterModelName: Teacher14aFilterModel.filterName,
  formModel: null,
  childBlocks: [],
),
Note: The filter plays a crucial role in determining the total number of ITEM(s) matching its criteria. If the filter criteria change, the current page of the BlockNumberPagination will be reset to 1.

3. DebugBlockStateView

DebugBlockStateView is a widget that allows you to view the state of a block, including pagination status. This widget is helpful for you during application development:
  • FlutterArtist DebugBlockStateView

4. BlockNumberPagination

Using BlockNumberPagination is straightforward. The two most important parameters to note are block and visiblePagesCount.
BlockNumberPagination
class BlockNumberPagination extends BlockPagination {
  final EdgeInsets padding;
  final int visiblePagesCount;

  const BlockNumberPagination({
    super.key,
    required super.block,
    required super.description,
    required super.ownerClassInstance,
    this.padding = EdgeInsets.zero,
    required this.visiblePagesCount,
  });

  ...
}
block
The Block used for pagination. This is the primary data source that the widget listens to for updating page states.
visiblePagesCount
The maximum number of visible page indices that users can click to navigate. If the total page count exceeds this value, the framework automatically handles truncation (e.g., using "...").
Placing BlockNumberPagination into the UI is seamless. The framework automatically handles the wiring between the pagination bar and the data within the Block.
BlockNumberPagination(
  block: teacher14aBlock,
  description: null,
  ownerClassInstance: this,
  visiblePagesCount: 10,
),
Full Source Code:
teacher14a_screen.dart
class Teacher14aScreen extends MyFaceScreen {
  static const String routeName = "/teacher14a";

  const Teacher14aScreen({super.key});

  @override
  Widget buildMainContent(BuildContext context) {
    Teacher14aShelf shelf = FlutterArtist.storage.findShelf();
    Teacher14aBlock teacher14aBlock = shelf.findTeacher14aBlock();
    Teacher14aFilterModel teacher14aFilterModel = shelf
        .findTeacher14aFilterModel();

    return Padding(
      padding: const EdgeInsets.all(10),
      child: LeftRightContainer(
        spacing: 20,
        arrowTopPosition: 10,
        fixedSizeWidth: 260,
        minSideWidth: 320,
        autoShowTwoSidesIfPossible: true,
        start: _buildLeft(teacher14aFilterModel, teacher14aBlock),
        end: _buildRight(teacher14aBlock),
      ),
    );
  }

  Widget _buildRight(Teacher14aBlock teacher14aBlock) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.start,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        ExampleOverviewBar(example: example_teacher14a),
        SizedBox(height: 10),
        BlockControlBar(
          description: null,
          ownerClassInstance: this,
          block: teacher14aBlock,
          config: BlockControlBarConfig(
            allowRefreshButton: true,
            allowQueryButton: true,
            allowCreateButton: false,
            allowSaveButton: false,
            allowDeleteButton: false,
            allowBackButton: false,
            allowDebugFormModelViewerButton: false,
            allowDebugFilterCriteriaViewerButton: true,
          ),
        ),
        SizedBox(height: 10),
        Expanded(child: Teacher14aGridItemsView(block: teacher14aBlock)),
        SizedBox(height: 10),
        BlockNumberPagination(
          block: teacher14aBlock,
          description: null,
          ownerClassInstance: this,
          visiblePagesCount: 10,
        ),
      ],
    );
  }

  Widget _buildLeft(
    Teacher14aFilterModel teacher14aFilterModel,
    Teacher14aBlock teacher14aBlock,
  ) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.start,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Teacher14aFilterPanel(filterModel: teacher14aFilterModel),
        SizedBox(height: 10),
        Expanded(
          child: SingleChildScrollView(
            child: DebugBlockStateView(
              block: teacher14aBlock,
              vertical: false,
              debugBlockOptions: null,
              debugFormOptions: null,
              debugPaginationOptions: DebugPaginationOptions(),
            ),
          ),
        ),
      ],
    );
  }

  @override
  String getTopMenuTitle() {
    return "[Pagination] Teacher14a";
  }

  @override
  String getTopMenuSubtitle() {
    return "BlockNumberPagination";
  }
}
No ADS
No ADS