Skip to content

Conversation

@gimmyhehe
Copy link
Member

@gimmyhehe gimmyhehe commented Dec 13, 2025

PR

修复visibleColumn变化时,会删除掉新插入数据问题

PR Checklist

Please check if your PR fulfills the following requirements:

  • The commit message follows our Commit Message Guidelines
  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been added / updated (for bug fixes / features)

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • Other... Please describe:

What is the current behavior?

Issue Number: N/A

What is the new behavior?

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

Summary by CodeRabbit

  • New Features

    • Added a grid toolbar with local storage to persist grid configuration and personalization across sessions.
    • Added a personalization panel to toggle column visibility dynamically.
  • Bug Fixes

    • Improved data restoration and loading to make row revert/reload and editable-row behavior more consistent.
  • Tests

    • Expanded tests to cover grid customization, column visibility toggling, and editable-row workflows.

✏️ Tip: You can customize this high-level summary in your review settings.

@github-actions github-actions bot added the bug Something isn't working label Dec 13, 2025
@coderabbitai
Copy link

coderabbitai bot commented Dec 13, 2025

Walkthrough

Adds a TinyGridToolbar to grid demos with local-storage settings; refactors grid data handling to prefer rawData over tableSynchData; updates normalization to derive editable columns from full column set and react to changes; expands a test to cover personalization panel column toggling.

Changes

Cohort / File(s) Summary
Toolbar Integration
examples/sites/demos/pc/app/grid/data-source/undefined-field-defalut-value-composition-api.vue, examples/sites/demos/pc/app/grid/data-source/undefined-field-defalut-value.vue
Import and register TinyGridToolbar from @opentiny/vue; add a toolbar template to the TinyGrid using TinyGridToolbar with local storage settings.
Test Expansion
examples/sites/demos/pc/app/grid/data-source/undefined-field-defalut-value.spec.js
Add locator for custom grid panel and extend test to add a row, open personalization/settings panel, toggle visibility of the "地址" column, assert column visibility change, and verify row count and editability remain correct.
Composable: data normalization
packages/vue/src/grid/src/composable/useNormalData.ts
Change parameter from visibleColumntableFullColumn; add editorColumns/editorColumnKey state; watch tableFullColumn to derive editable column keys; watch editorColumns and rawData to call $table.defineField for normalization and bump rawDataVersion.
Edit revert behavior
packages/vue/src/grid/src/edit/src/methods.ts
_revertData now uses rawData instead of tableSynchData when reverting or reloading rows with no explicit argument.
Table data methods
packages/vue/src/grid/src/table/src/methods.ts
loadTableData no longer assigns tableSynchData; getData fallback changed from this.tableSynchData to [] when rawData is absent.
Table initialization
packages/vue/src/grid/src/table/src/table.ts
Pass tableFullColumn (not visibleColumn) into useNormalData, aligning composable inputs with full column set.
Manifest
package.json
Included in manifest listing (no functional change described).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Pay special attention to packages/vue/src/grid/src/composable/useNormalData.ts for correctness of the new watchers, the editorColumns key derivation (watch triggers and sorting), and the use of $table.defineField to ensure field normalization doesn't introduce regressions.
  • Verify packages/vue/src/grid/src/table/src/methods.ts and packages/vue/src/grid/src/edit/src/methods.ts changes don't create edge cases where data is unexpectedly empty after removing tableSynchData.
  • Confirm table.ts change (passing tableFullColumn) matches the composable's expectations and that downstream reactive flows (e.g., rawDataVersion) still trigger UI updates.
  • Review updated example/demo imports/registrations for TinyGridToolbar and the extended test for flakiness related to personalization panel timing.

Poem

🐇 I nibble keys and polish rows tonight,
A tiny toolbar twinkles with stored light,
Fields reshape, columns hide or show,
From sync to raw, the data grows.
Hop, edit, save — the grid is bright! ✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main fix: preventing deletion of newly inserted rows when visible columns change, which aligns with all file modifications.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch cgm/fix-visible-column-change

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/vue/src/grid/src/edit/src/methods.ts (1)

254-285: Avoid reloading with possibly-undefined rawData
If this.rawData can ever be undefined/non-array, return this.reloadData(rawData) (Line 284) can behave like “clear”. Normalize once and reuse.

  _revertData(rows, field) {
-    let { rawData } = this
+    const rawData = Array.isArray(this.rawData) ? this.rawData : []
 
     if (arguments.length && rows && !isArray(rows)) {
       rows = [rows]
     }
 
     if (!arguments.length) {
-      rows = rawData || []
+      rows = rawData
     }
@@
-    return this.reloadData(rawData)
+    return this.reloadData(rawData)
   },
packages/vue/src/grid/src/table/src/methods.ts (1)

753-765: getData() should not ignore tableFullData when rawData is unset/stale
const allRows = this.rawData || [] (Line 754) can return [] even when tableFullData is populated (e.g., via loadTableData). Safer fallback:

  getData(rowIndex) {
-    const allRows = this.rawData || []
+    const allRows = this.rawData || this.tableFullData || []
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5bdfec1 and 154b322.

📒 Files selected for processing (6)
  • examples/sites/demos/pc/app/grid/data-source/undefined-field-defalut-value-composition-api.vue (2 hunks)
  • examples/sites/demos/pc/app/grid/data-source/undefined-field-defalut-value.spec.js (2 hunks)
  • examples/sites/demos/pc/app/grid/data-source/undefined-field-defalut-value.vue (2 hunks)
  • packages/vue/src/grid/src/composable/useNormalData.ts (2 hunks)
  • packages/vue/src/grid/src/edit/src/methods.ts (2 hunks)
  • packages/vue/src/grid/src/table/src/methods.ts (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: PR E2E Test (pnpm test:e2e3)
🔇 Additional comments (6)
packages/vue/src/grid/src/composable/useNormalData.ts (2)

3-21: Watcher split matches the bugfix intent (don’t reload on column changes)
Good change: rawDataVersion bumps only on rawData updates (Line 10-21), avoiding unintended reloads from column-visibility changes. Consider a small safety guard to avoid runtime errors if $table isn’t ready:

-  const $table: any = hooks.getCurrentInstance()?.proxy
+  const $table: any = hooks.getCurrentInstance()?.proxy
@@
-      _data.forEach((row) => $table.defineField(row))
+      $table && _data.forEach((row) => $table.defineField(row))

23-33: Ensure insertList rows are normalized without triggering a data reload
This watcher (Line 23-33) looks correct for the reported issue: it updates row shape for rawData and editStore.insertList while not bumping rawDataVersion (so inserted rows shouldn’t be dropped).

packages/vue/src/grid/src/table/src/methods.ts (1)

290-317: loadTableData() intentionally does not update rawData—document its contract to prevent API misuse.

The current design uses separate data paths: loadTableData() updates tableFullData for display (e.g., filtered data in select/grid-select), while rawData remains the source of truth. External callers in select and grid-select do not call getData() after loadTableData(), so no active bug exists. However, the API contract is unclear. Future developers may incorrectly assume getData() reflects changes from loadTableData(). Consider:

  1. Document loadTableData() as an internal method intended only for display updates (e.g., filtering) that do not affect the source data.
  2. Alternatively, update getData() to fall back to tableFullData when rawData is unavailable or stale, ensuring consistency.
examples/sites/demos/pc/app/grid/data-source/undefined-field-defalut-value.spec.js (1)

7-51: Selector scoping and test isolation concerns require HTML structure verification

The test does use page.locator('.tiny-grid-custom__setting-btn') without scoping to demo, which could cause cross-demo collisions if multiple grid instances exist on the page. However, the proposed fix of scoping to demo.locator('.tiny-grid-custom__setting-btn') assumes the settings button is a child of the demo container—this needs verification against the actual HTML structure.

Regarding localStorage: Playwright does not clear localStorage by default on page.goto(), so persisted column visibility settings could cause test flakiness across runs. However, localStorage.clear() is only necessary if the grid customization state is actually stored in localStorage.

Before applying the suggested fixes, confirm:

  • Whether .tiny-grid-custom__setting-btn is nested inside the demo element or is a global component
  • Whether the grid custom settings are persisted via localStorage or session state
examples/sites/demos/pc/app/grid/data-source/undefined-field-defalut-value.vue (2)

28-28: LGTM!

The import statement correctly includes TinyGridToolbar, which is necessary for the new toolbar functionality.


35-36: LGTM!

Component registrations are correct. Both TinyButton (which was previously used in the template) and the newly added TinyGridToolbar are now properly registered.

Comment on lines +5 to +7
<template #toolbar>
<tiny-grid-toolbar id="undefined-field-defalut-value" :setting="{ storage: 'local' }"></tiny-grid-toolbar>
</template>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Typo in the toolbar ID attribute.

The ID contains "defalut" instead of "default". While this is consistent with the filename, it's still a typo that should be corrected.

Apply this diff to fix the typo:

       <template #toolbar>
-        <tiny-grid-toolbar id="undefined-field-defalut-value" :setting="{ storage: 'local' }"></tiny-grid-toolbar>
+        <tiny-grid-toolbar id="undefined-field-default-value" :setting="{ storage: 'local' }"></tiny-grid-toolbar>
       </template>

Note: You may also want to rename the file itself to maintain consistency.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<template #toolbar>
<tiny-grid-toolbar id="undefined-field-defalut-value" :setting="{ storage: 'local' }"></tiny-grid-toolbar>
</template>
<template #toolbar>
<tiny-grid-toolbar id="undefined-field-default-value" :setting="{ storage: 'local' }"></tiny-grid-toolbar>
</template>
🤖 Prompt for AI Agents
In
examples/sites/demos/pc/app/grid/data-source/undefined-field-defalut-value.vue
around lines 5 to 7, the toolbar id contains a typo "defalut" instead of
"default"; update the id attribute value to "undefined-field-default-value" to
correct the spelling, and optionally rename the file to
examples/sites/demos/pc/app/grid/data-source/undefined-field-default-value.vue
(and update any imports/references) to keep filename consistent with the
corrected id.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 154b322 and 32c7a26.

📒 Files selected for processing (3)
  • packages/vue/src/grid/src/composable/useNormalData.ts (1 hunks)
  • packages/vue/src/grid/src/edit/src/methods.ts (2 hunks)
  • packages/vue/src/grid/src/table/src/table.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/vue/src/grid/src/edit/src/methods.ts
🧰 Additional context used
🧬 Code graph analysis (1)
packages/vue/src/grid/src/table/src/table.ts (1)
packages/vue/src/grid/src/composable/useNormalData.ts (1)
  • useNormalData (3-69)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: PR E2E Test (pnpm test:e2e3)
🔇 Additional comments (6)
packages/vue/src/grid/src/composable/useNormalData.ts (5)

3-3: LGTM! API signature updated correctly.

The refactoring from visibleColumn to tableFullColumn aligns with the PR objective to fix the issue where changing visibleColumn would delete newly inserted rows. By tracking the full column set instead of just visible columns, the data normalization can react properly to column visibility changes.


4-4: LGTM! Explicit typing improves clarity.

Adding the explicit type annotation for $table improves code readability, even though it's typed as any.


9-11: LGTM! New state for tracking editable columns.

The introduction of editorColumns and editorColumnKey enables the new logic to track which columns are editable and react to changes in the editable column set.


47-59: LGTM! Raw data normalization logic is sound.

The watcher correctly normalizes fields for rawData only (not insertList), as indicated by the comment that temporary insert data will be cleaned up later. The version increment triggers downstream cache updates and data handling via the existing rawDataVersion watcher.


34-45: No conflict between watchers—the design is intentional.

The editorColumns watcher processes both insertList and rawData because column structure changes require normalizing all data. The subsequent rawData watcher explicitly excludes insertList, as documented in its inline comment: "不处理临时插入数据,因为后续会被清理掉" (doesn't process insertList because it will be cleaned up later). The insertList is cleared when table data is loaded via loadTableData(), confirming it's temporary and the design is sound.

packages/vue/src/grid/src/table/src/table.ts (1)

711-711: LGTM! Integration point updated correctly.

The change from visibleColumn to tableFullColumn correctly aligns with the refactored useNormalData API. This enables the data normalization logic to track all columns (not just visible ones), which should fix the reported issue where changing visibleColumn would delete newly inserted rows.

Comment on lines +13 to +32
hooks.watch(tableFullColumn, (_tableFullColumn) => {
let columns = []
let columnKeys = []

for (let i = 0; i < _tableFullColumn.length; i++) {
const column = _tableFullColumn[i]

if (column.property && column.editor) {
columns.push(column)
columnKeys.push(column.propety)
}
}

const keyString = columnKeys.sort().join()

if (editorColumnKey.value !== keyString) {
editorColumnKey.value = keyString
editorColumns.value = columns
}
})
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical typo: column.propety should be column.property.

Line 22 contains a typo that will cause the columnKeys array to collect undefined values, breaking the key comparison logic and potentially causing incorrect behavior when columns change.

Apply this diff to fix the typo:

       if (column.property && column.editor) {
         columns.push(column)
-        columnKeys.push(column.propety)
+        columnKeys.push(column.property)
       }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
hooks.watch(tableFullColumn, (_tableFullColumn) => {
let columns = []
let columnKeys = []
for (let i = 0; i < _tableFullColumn.length; i++) {
const column = _tableFullColumn[i]
if (column.property && column.editor) {
columns.push(column)
columnKeys.push(column.propety)
}
}
const keyString = columnKeys.sort().join()
if (editorColumnKey.value !== keyString) {
editorColumnKey.value = keyString
editorColumns.value = columns
}
})
hooks.watch(tableFullColumn, (_tableFullColumn) => {
let columns = []
let columnKeys = []
for (let i = 0; i < _tableFullColumn.length; i++) {
const column = _tableFullColumn[i]
if (column.property && column.editor) {
columns.push(column)
columnKeys.push(column.property)
}
}
const keyString = columnKeys.sort().join()
if (editorColumnKey.value !== keyString) {
editorColumnKey.value = keyString
editorColumns.value = columns
}
})
🤖 Prompt for AI Agents
In packages/vue/src/grid/src/composable/useNormalData.ts around lines 13 to 32
there is a typo: column.propety is used when pushing keys which yields
undefined; change that to column.property so columnKeys collects the actual
property values (ensure the push uses column.property and nothing else needs
changing).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants