Skip to content

Cross-page "Select all N matching" can never appear in the console — totalMatching is only written by ObjectGrid's own loader, which never runs under ListView's external pagination #4464

Description

@baozhoutao

Found by a retest of records-forms.bulk-select-all-matching (framework QA run objectstack-ai/objectstack#7439) against the console at pin 6314e87f2d49. The fix under retest — #4140 (the selectionResetKey bump) — is verified working; this is a separate, pre-existing gap that the retest was able to reach for the first time.

Symptom

Selecting an entire page in a genuinely server-paginated grid shows only N selected | Delete | Clear. The cross-page banner never renders: [data-testid=bulk-cross-page-banner] and [data-testid=bulk-select-all-matching] are both absent, for any match-set size. Reproduced on two fresh loads.

Reproduction

  1. As admin, author a paginated view:
    PUT /api/v1/meta/view/showcase_contact.rt5_paged with
    config {type:'grid', data:{provider:'object',object:'showcase_contact'}, filter:[{field:'account',operator:'equals',value:'<Northwind id>'}], pagination:{pageSize:10}}
  2. Open /_console/apps/com.example.showcase/showcase_contact?view=showcase_contact.rt5_paged.
    The grid pages server-side for real — GET /api/v1/data/showcase_contact?top=10&filter=…total=26, 10 rows, count bar "26 records", pager "Page 1 of 3".
  3. Click the header select-all checkbox to select the whole visible page.

Expected: BulkActionBar shows "All 10 on this page are selected." plus a "Select all 26 matching" button.
Actual: no banner — only 10 selected | Delete | Clear.

Root cause

BulkActionBar gates the banner on:

const showCrossPageAffordance =
  !allMatchingSelected &&
  typeof totalMatching === 'number' &&
  typeof pageSize === 'number' && pageSize > 0 &&
  selectedRows.length >= pageSize &&
  totalMatching > pageSize;

ObjectGrid passes totalMatching={singleSelection ? undefined : totalMatching}, and the only writer of that state is setTotalMatching(...) inside ObjectGrid's own data loader (ObjectGrid.tsx ~:710).

In the console the grid is hosted by ListView, which fetches rows itself and passes manualPagination:true, rowCount:serverTotal, page, pageSize, onPageChange down (plugin-list/src/ListView.tsx ~:2859-2864). So externalManualPagination is true, ObjectGrid's loader never runs, totalMatching stays undefined, and the banner condition is permanently false.

The tell that the data is right there: the pager shows the correct page count because it reads
manualRowCount = externalManualPagination ? rest.rowCount : totalMatching
the grid has the real total on the external path; it just never reaches BulkActionBar.

Suggested fix: fall back to rest.rowCount when externalManualPagination is on.

This is the same shape as #4138 (fixed): a feature gated on internal-data state that the console's external-data path never populates. Worth a sweep for other totalMatching-style state with a single internal writer.

Consequence for the checklist item

With the affordance unreachable, three further clauses cannot run at all: the collected-id set can't be compared against the filtered API count, the aggregate-vs-per-record distinction over the matching set is undefined, and the HARD_CAP (5000) path is doubly out of reach. Only the clause #4140 addressed is green.

Two scope notes, stated plainly

Fixture correction worth recording

The previous run recorded these clauses blocked(fixture) believing no object exceeds the page window. Half of that is true — the stock console fetches top=100 and showcase_contact's 32 rows fit one page — but the blocker is not a hard 100-row limit: authoring a view with config.pagination.pageSize turns on real server-side paging, which is what made this defect reachable. (The probe view was deleted afterwards; no repo file was touched.)

Source

Retest of records-forms.bulk-select-all-matching at console pin 6314e87f2d49, framework b602d536.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions