Repository navigation
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Confidence Score: 5/5Safe to merge — typed commands and selectors are thoroughly guarded, the controlledSlice primitive is well-tested, and all companion controls are migrated consistently. All nine state slices are correctly wired through controlledSlice with appropriate read/write normalization hooks. Every command guards against unknown column/row ids via optional chaining or explicit checks. The nextPage/previousPage asymmetry is intentional and correct: TanStack's client-side nextPage is an unclamped increment (requiring the facade guard), while previousPage uses Math.max(0, old-1) internally (no guard needed). The new specs cover all documented edge cases. No regressions found in the companion control migrations. No files require special attention.
|
| Filename | Overview |
|---|---|
| libs/ng-advanced-table/src/utils/controlled-slice.util.ts | New utility that encapsulates the controlled/internal signal pattern with optional read/write normalization hooks; well-tested with 7 unit specs covering all branches. |
| libs/ng-advanced-table/src/table/table.ts | Implements all 10 typed commands and 9 typed selectors on NatTableUiController; nextPage guards on canNextPage(), previousPage delegates to TanStack which clamps at 0 internally, and all column/row commands no-op on unknown ids via optional chaining or explicit checks. |
| libs/ng-advanced-table/src/domain-logic/table.state.ts | Replaces 9 hand-synced controlled/internal signal pairs with controlledSlice instances and delegates TanStack construction to table-instance.factory and intl to NatTableIntlService; updateState correctly re-resolves all 9 slices on every call (consistent with prior behavior). |
| libs/ng-advanced-table/src/domain-logic/table-instance.factory.ts | Extracts TanStack table creation from NatTableState; callbacks correctly pass firstPageUpdater on globalFilter/columnFilter changes and delegate all state mutations back through store.updateState. |
| libs/ng-advanced-table/src/domain-logic/table-intl.service.ts | New leaf service that resolves locale/intl/a11y-text, injecting only NatTableService and NAT_TABLE_INTL to avoid DI cycles; cleanly mirrors what was in NatTableState before. |
| libs/ng-advanced-table/src/common/ui-controller.type.ts | Replaces single generic patchState with 10 typed command methods and adds 9 typed signal selectors; table accessor deprecated with clear JSDoc, NatTableColumnVisibilityItem exported for consumers. |
| libs/ng-advanced-table/src/domain-logic/table-a11y.service.ts | Moves ARIA id computeds and resolved a11y text computeds from NatTableState here; delegates intl to NatTableIntlService; resizeCommit is no longer cleared inside the effect (intentional, flagged in previous review round). |
| libs/ng-advanced-table/components/feature/table-column-visibility/table-column-visibility.ts | Cleanly migrated from getAllLeafColumns()/toggleVisibility() to columnVisibility() selector + setColumnVisible() command; canToggle still computed locally to handle the last-visible-column guard. |
| libs/ng-advanced-table/render-metrics/common/contracts.type.ts | NatTableRenderMetricsController updated from patchState to typed commands; correctly kept as a smaller subset contract (no sorting/rowSelection/columnVisibility) since the filter component only needs columnFilters. |
| libs/ng-advanced-table/render-metrics/feature/filter/filter.ts | Clears filter with undefined (was null) to match TanStack's setFilterValue contract for removal; delegates to setColumnFilter which routes through onColumnFiltersChange with firstPageUpdater for automatic page reset. |
| libs/ng-advanced-table/src/table/table.pagination-controller.spec.ts | New spec with 13 tests covering pageCount edges, navigation guards, atomic setPageSize, and filter-driven page resets; includes important comment documenting why nextPage needs a guard but previousPage does not. |
| libs/ng-advanced-table/src/table/table.commands-controller.spec.ts | New spec with 11 tests covering sort set/replace/remove, visibility toggle with canHide guard, selection set/clear with disabled guard, and unknown-id no-ops for all commands. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
subgraph Controller["NatTableUiController (NatTable)"]
CMD["Typed Commands\nsetGlobalFilter / setColumnFilter\nsetColumnSort / setColumnVisible\nsetRowSelected / clearRowSelection\nsetPageSize / goToPage\nnextPage / previousPage"]
SEL["Typed Selectors (Signals)\npagination / pageCount\ncanPreviousPage / canNextPage\nglobalFilter / columnFilters\nsorting / columnVisibility / rowSelection"]
end
subgraph Store["NatTableState"]
CS["controlledSlice x9\n(sorting, globalFilter, columnFilters,\ncolumnVisibility, columnOrder,\ncolumnPinning, columnSizing,\nrowSelection, pagination)"]
US["updateState()\nresolves + commits all slices"]
end
subgraph Factory["table-instance.factory"]
TI["createAngularTable\nwith onXxxChange callbacks\n-> store.updateState()"]
end
subgraph Services["Leaf Services"]
IS["NatTableIntlService\n(locale + a11y text)"]
AS["NatTableA11yService\n(ARIA ids + announcements)"]
end
CompControls["Companion Controls\n(NatTablePager, NatTablePageSize,\nNatTablePagination, NatTableColumnVisibility,\nNatTableSearch, NatRenderMetricsFilter)"]
CMD -->|"delegates to table.setXxx()"| TI
TI -->|"onChange -> updateState"| US
US --> CS
CS -->|"merged()"| SEL
SEL -->|"consumed by"| CompControls
IS -->|"localeId, resolvedAccessibilityText"| AS
IS -->|"localeId"| Store
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
subgraph Controller["NatTableUiController (NatTable)"]
CMD["Typed Commands\nsetGlobalFilter / setColumnFilter\nsetColumnSort / setColumnVisible\nsetRowSelected / clearRowSelection\nsetPageSize / goToPage\nnextPage / previousPage"]
SEL["Typed Selectors (Signals)\npagination / pageCount\ncanPreviousPage / canNextPage\nglobalFilter / columnFilters\nsorting / columnVisibility / rowSelection"]
end
subgraph Store["NatTableState"]
CS["controlledSlice x9\n(sorting, globalFilter, columnFilters,\ncolumnVisibility, columnOrder,\ncolumnPinning, columnSizing,\nrowSelection, pagination)"]
US["updateState()\nresolves + commits all slices"]
end
subgraph Factory["table-instance.factory"]
TI["createAngularTable\nwith onXxxChange callbacks\n-> store.updateState()"]
end
subgraph Services["Leaf Services"]
IS["NatTableIntlService\n(locale + a11y text)"]
AS["NatTableA11yService\n(ARIA ids + announcements)"]
end
CompControls["Companion Controls\n(NatTablePager, NatTablePageSize,\nNatTablePagination, NatTableColumnVisibility,\nNatTableSearch, NatRenderMetricsFilter)"]
CMD -->|"delegates to table.setXxx()"| TI
TI -->|"onChange -> updateState"| US
US --> CS
CS -->|"merged()"| SEL
SEL -->|"consumed by"| CompControls
IS -->|"localeId, resolvedAccessibilityText"| AS
IS -->|"localeId"| Store
Reviews (4): Last reviewed commit: "refactor(docs): 🎨 improve table capabil..." | Re-trigger Greptile
324ccb1 to
b9c8714
Compare
…ice state Extract the controlled-vs-internal merge rule (read: controlled ?? internal, write: commit only when uncontrolled) into one small reusable primitive with a two-hook read/write contract. This lets the store express the rule once per slice instead of hand-syncing it across the merge and commit paths, without changing behaviour. Groundwork for the RFC #226 state de-duplication.
Reduce the coupling around NatTableState without changing runtime behaviour or the controlled/uncontrolled state feature. Four coherent changes that share the same core files (table.ts, table.state.ts, the controller contract) and so land together: - De-bulk the store: collapse the 9 hand-synced controlled/internal signal pairs onto controlledSlice, move the TanStack table construction into a table-instance factory, and split intl + a11y-text derivation into a leaf NatTableIntlService and the existing NatTableA11yService. table.state.ts drops from 635 to ~542 code lines; the max-lines disable is rewritten (kept, scoped) to name the genuinely irreducible residual. - Typed-command facade: replace the raw-Updater-leaking NatTableUiController.patchState with typed commands (setGlobalFilter, setColumnFilter, setPageSize, goToPage, nextPage, previousPage). Companion controls and the internal specs move off updater closures. BREAKING: patchState removed from the controller contract. - A11y read-only: the a11y service no longer clears state.resizeCommit; that clear moves to resize start (resize lifecycle owns it), so a11y only reads. - Read selectors: expose typed pagination/pageCount/canPreviousPage/ canNextPage/globalFilter/columnFilters signals; migrate the pagination, page-size, pager, search and render-metrics filter controls off the raw table. table stays on the controller (deprecated) for the rich column-object reads that column-visibility and export still need. Not done (deliberate): RFC #226 "one source of truth" — it would delete the documented per-slice controlled mode that several demos rely on.
The consumer-owned search example (and its skill-doc/composition mirrors) now
call controller.setGlobalFilter(value) instead of hand-writing a
patchState({ globalFilter, pagination }) updater closure, matching the new
typed-command controller surface.
…yped commands
- replace `patchState(...)` with intent-named command methods
- introduce typed signal selectors for state reads
- deprecate raw `table` accessor for improved clarity
BREAKING CHANGE: consumers must migrate from `controller.patchState({...})`
to the corresponding command methods and use typed selectors for state reads.
- migrate main-added sort-pin spec off removed table.patchState -> table.setSorting - drop now-unused PaginationState import in table-search - regenerate docs registry from HEAD composition.md (setGlobalFilter/globalFilter)
Delegate pageCount to the state's resolvedPageCount, mark the raw table accessor deprecated in favor of typed commands, route internal command implementations through state.table instead of the public alias, and guard nextPage/goToPage against out-of-range navigation.
…nSort Point the sorting and responsive-capabilities guides (and the generated docs registry mirror) at setColumnSort instead of raw table access, and update the table-patterns skill reference to match.
Add setColumnSort, setColumnVisible, setRowSelected, and clearRowSelection commands plus sorting/columnVisibility/rowSelection selectors to NatTableUiController, migrate table-column-visibility and header-actions off the deprecated raw table accessor, and extend the testing contracts/data helpers to cover the new commands. table-export keeps direct table access as the deliberate exception (export needs the raw row/column model).
e7e2b92 to
df1be3b
Compare
|
i think the discussion here is the following. Do we want tanstack to be the adapter or the reducer? This architecture has it more as the reducer and central state store. What i see: Pros
Cons
I'd say this PR establishes the better fit for this library (going more reducer mode). But i'd say we need to make sure that It's clearly stated. @sp90 What is your take on this? |
|
What i would improve on:
|
|
I love the fact that we kind of centralize state big win, but im also kind of thoughtful of throwing the tanstack familarity out the window as you also point to @VaggelisKa. I dont paticually think its a need but it is a tradeoff we need to agree we're happy with |
What changed
NatTableState: the 9 hand-synced controlled/internal signal pairs collapse onto acontrolledSliceprimitive, TanStack table creation moves to atable-instancefactory, and intl + a11y-text derivation split into a leafNatTableIntlServiceand the existingNatTableA11yService. The store drops from 635 to ~542 code lines; itsmax-linesdisable is rewritten (kept, scoped) to name the genuinely irreducible residual.NatTableUiController:patchState(updater)is replaced withsetGlobalFilter,setColumnFilter,setColumnSort,setColumnVisible,setRowSelected,clearRowSelection,setPageSize,goToPage,nextPage,previousPage. Commands are absolute and safe: unknown column/row ids no-op,nextPageguards oncanNextPage, andgoToPageclamps to the valid page range (TanStack itself only clamps the upper bound in manual pagination).pagination,pageCount,canPreviousPage,canNextPage,globalFilter,columnFilters,sorting,rowSelection, andcolumnVisibility(per-column{ id, label, visible, canHide }items, labels resolved the same way the built-in controls resolve them).state.resizeCommit. That clear moves to resize start, so a11y only reads state.Impact on existing code
patchStateis removed from the controller contract. Companion controls and any consumer that drove state through updater closures now call the typed commands.NatTableService.patchState(config), the surface's config method, is a different API and is unchanged.controller.tableis@deprecatedand every previous use case now has a typed alternative. The column-visibility control runs entirely oncolumnVisibility()+setColumnVisible(). The one deliberate exception is the export directive: its handler context exposes the raw TanStacktableby contract, so it keeps a single documented.tableread..tablecomputed in the showcase search component is removed.setColumnSort(sorting, responsive-capabilities, header-actions jsdoc, best-practise skills); the rawtable.setSorting(...)path stays documented for multi-column sorts only.Test plan
table.pagination-controller.spec.ts(13 tests: pageCount edges incl. pagination-disabled and manual mode, navigation guards, atomicsetPageSize, filter-driven first-page resets) andtable.commands-controller.spec.ts(11 tests: sort set/replace/remove, visibility toggle +canHideguard, selection set/clear + disabled guard, unknown-id no-ops).Closes #226