Conversation
Reviewer's guide (collapsed on small PRs)Reviewer's GuideAdjusts table editing behavior to correctly clone models only for DataTableDynamicContext scenarios, fixes object cloning to use the runtime type, and ensures dynamic table edits update the underlying cached and DataTable-backed data objects. Sequence diagram for table row edit with DataTableDynamicContext cloningsequenceDiagram
actor User
participant Table
participant Utility
participant DynamicContext
User->>Table: EditAsync()
alt SelectedRows empty
Table-->>User: return
else SelectedRows not empty
Table->>Table: ToggleLoading(true)
alt IsTracking true or DynamicContext not DataTableDynamicContext
Table->>Table: EditModel = SelectedRows[0]
else DynamicContext is DataTableDynamicContext
Table->>Utility: Clone(SelectedRows[0])
Utility-->>Table: clonedModel
Table->>Table: EditModel = clonedModel
end
alt OnEditAsync not null
Table->>Table: OnEditAsync(EditModel)
end
Table->>Table: ToggleLoading(false)
Table-->>User: open edit UI
end
Sequence diagram for dynamic cell value change updating cache and DataTablesequenceDiagram
participant DynamicTable as DataTableDynamicContext
participant DynamicItem as IDynamicObject
participant Column as ITableColumn
participant Cache as DataCache
participant CacheItem
participant DataRow
DynamicTable->>DynamicTable: OnCellValueChanged(DynamicItem, Column, val)
DynamicTable->>Cache: TryGetValue(DynamicItem.DynamicObjectPrimaryKey)
alt Cache hit
Cache-->>DynamicTable: CacheItem
DynamicTable->>CacheItem: Utility.SetPropertyValue(CacheItem, Column.GetFieldName(), val)
alt CacheItem.Row not null
DynamicTable->>DataRow: update cell value
end
else Cache miss
Cache-->>DynamicTable: not found
end
Updated class diagram for Table editing and dynamic data handlingclassDiagram
class TableComponent {
bool IsTracking
object? DynamicContext
IList~object~ SelectedRows
object? EditModel
Func~object,Task~? OnEditAsync
Task EditAsync()
Task ToggleLoading(bool isLoading)
}
class DataTableDynamicContext {
Dictionary~string,DataCacheItem~ _dataCache
Task OnCellValueChanged(IDynamicObject item, ITableColumn column, object val)
}
class DataCacheItem {
string DynamicObjectPrimaryKey
object CacheObject
DataRow? Row
}
class IDynamicObject {
string DynamicObjectPrimaryKey
}
class ITableColumn {
string GetFieldName()
}
class ObjectExtensions {
static void Clone~TModel~(TModel source, TModel item)
}
class Utility {
static TModel Clone~TModel~(TModel source)
static void SetPropertyValue~TTarget,TValue~(TTarget target, string propertyName, TValue value)
}
class DataRow {
object this[string columnName]
}
TableComponent --> DataTableDynamicContext : uses DynamicContext
TableComponent --> Utility : calls Clone
TableComponent --> ObjectExtensions : uses Clone extension
TableComponent --> IDynamicObject : SelectedRows items may implement
DataTableDynamicContext --> IDynamicObject : parameter item
DataTableDynamicContext --> ITableColumn : parameter column
DataTableDynamicContext --> DataCacheItem : uses _dataCache
DataTableDynamicContext --> Utility : calls SetPropertyValue
DataCacheItem --> DataRow : contains Row
ObjectExtensions ..> Utility : may delegate to Clone
IDynamicObject <|.. DataCacheItem
IDynamicObject <|.. DynamicRuntimeItem
class DynamicRuntimeItem {
string DynamicObjectPrimaryKey
}
File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- The ternary in
EditAsynccombiningIsTrackingandDynamicContext is not DataTableDynamicContextis a bit hard to scan; consider extracting this into a clearly named local likebool shouldCloneForDynamicContextto make the edit behavior easier to understand and maintain. - In
OnCellValueChanged,Utility.SetPropertyValue<object, object?>assumes the target property exists and is settable; consider handling or short‑circuiting when the property is missing/readonly to avoid runtime exceptions when dynamic column definitions and cached items diverge.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The ternary in `EditAsync` combining `IsTracking` and `DynamicContext is not DataTableDynamicContext` is a bit hard to scan; consider extracting this into a clearly named local like `bool shouldCloneForDynamicContext` to make the edit behavior easier to understand and maintain.
- In `OnCellValueChanged`, `Utility.SetPropertyValue<object, object?>` assumes the target property exists and is settable; consider handling or short‑circuiting when the property is missing/readonly to avoid runtime exceptions when dynamic column definitions and cached items diverge.
## Individual Comments
### Comment 1
<location path="src/BootstrapBlazor/Components/Table/Table.razor.Toolbar.cs" line_range="655-656" />
<code_context>
await ToggleLoading(true);
- EditModel = (IsTracking || DynamicContext != null) ? SelectedRows[0] : Utility.Clone(SelectedRows[0]);
+
+ // 复制对象给编辑模型
+ EditModel = (IsTracking || DynamicContext is not DataTableDynamicContext)
+ ? SelectedRows[0]
+ : Utility.Clone(SelectedRows[0]);
</code_context>
<issue_to_address>
**issue (bug_risk):** Double-check the behavior change when DynamicContext is null compared to the previous condition.
With the new condition `(IsTracking || DynamicContext is not DataTableDynamicContext)`, the `DynamicContext == null` case now returns `SelectedRows[0]` instead of a clone. This changes previous copy-vs-reference behavior and may introduce in-place mutations where a safe copy was used before. Consider explicitly handling `DynamicContext == null` or clarifying in code/comments that this behavioral change is intentional.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #7917 +/- ##
===========================================
- Coverage 100.00% 99.99% -0.01%
===========================================
Files 765 765
Lines 34325 34332 +7
Branches 4710 4711 +1
===========================================
+ Hits 34325 34331 +6
- Partials 0 1 +1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR updates table editing behavior and DataTable-backed dynamic models to better support “Cancel” scenarios when using DataTableDynamicObject-based rows (fixes #7916).
Changes:
- Fix cloning to use the runtime type (
item.GetType()) soUtility.Cloneworks correctly whenTModelis an interface/base type (e.g.,IDynamicObject). - Ensure
DataTableDynamicContextkeeps the cached dynamic object’s properties in sync when a cell value changes. - Adjust
Table.EditAsynccloning logic to special-caseDataTableDynamicContext(intended to support cancel without mutating live rows).
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| src/BootstrapBlazor/Extensions/ObjectExtensions.cs | Clone now reflects over the runtime type, enabling correct cloning for dynamic/interface-typed models. |
| src/BootstrapBlazor/Dynamic/DataTableDynamicContext.cs | Updates cached dynamic object properties on cell edit so UI/model stays consistent with the underlying DataRow. |
| src/BootstrapBlazor/Components/Table/Table.razor.Toolbar.cs | Changes how EditModel is chosen (clone vs. live instance) for editing scenarios, targeting DataTable dynamic context cancel behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Link issues
fixes #7916
Summary By Copilot
Regression?
Risk
Verification
Packaging changes reviewed?
☑️ Self Check before Merge
Summary by Sourcery
Support canceling edits when using the DataTableDynamicObject model by correctly cloning and syncing dynamic table data.
Bug Fixes: