Skip to content

feat(Table): support validate InCell Mode#7437

Merged
celadaris merged 7 commits intomainfrom
EditMode.InCell-Fix
Dec 28, 2025
Merged

feat(Table): support validate InCell Mode#7437
celadaris merged 7 commits intomainfrom
EditMode.InCell-Fix

Conversation

@celadaris
Copy link
Copy Markdown
Collaborator

@celadaris celadaris commented Dec 28, 2025

Introduces an IsFormless parameter to ValidateForm, allowing it to operate without rendering a form element, which is used for in-cell editing in Table. Updates Table to use this mode for in-cell editing, ensures validation is performed, and manages EditContext accordingly. Also fixes validation logic and EditTemplate usage to support the new mode.

Link issues

fixes #7139

Summary By Copilot

Regression?

  • Yes
  • No

Risk

  • High
  • Medium
  • Low

Verification

  • Manual (required)
  • Automated

Packaging changes reviewed?

  • Yes
  • No
  • N/A

☑️ Self Check before Merge

⚠️ Please check all items below before review. ⚠️

  • Doc is updated/provided or not needed
  • Demo is updated/provided or not needed
  • Merge the latest code from the main branch

Summary by Sourcery

Add a formless validation mode to ValidateForm and integrate it with Table in-cell editing to enable proper validation without rendering a form element.

New Features:

  • Introduce an IsFormless mode in ValidateForm to provide validation and EditContext cascading without rendering a form element.
  • Enable Table in-cell editing rows to be wrapped in a formless ValidateForm for model validation and context management.

Bug Fixes:

  • Ensure the ValidateForm invalid state is correctly set even when no validation components are present.
  • Fix Table edit field rendering so in-cell edit templates participate in validation instead of skipping it.
  • Ensure in-cell update actions validate the current edit model and reuse the associated EditContext when saving.

Enhancements:

  • Expose the EditContext used by formless ValidateForm instances for consumers such as Table to reuse during save operations.

Introduces an IsFormless parameter to ValidateForm, allowing it to operate without rendering a form element, which is used for in-cell editing in Table. Updates Table to use this mode for in-cell editing, ensures validation is performed, and manages EditContext accordingly. Also fixes validation logic and EditTemplate usage to support the new mode.
@bb-auto
Copy link
Copy Markdown

bb-auto Bot commented Dec 28, 2025

Thanks for your PR, @celadaris. Someone from the team will get assigned to your PR shortly and we'll get it reviewed.

@bb-auto bb-auto Bot requested a review from ArgoZhang December 28, 2025 03:58
@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented Dec 28, 2025

Reviewer's Guide

Adds a formless mode to ValidateForm so it can participate in validation without rendering a

, and wires Table’s in‑cell editing to use this mode with proper EditContext reuse and validation behavior.

Sequence diagram for Table in‑cell update using formless ValidateForm

sequenceDiagram
    actor User
    participant Table as Table_TItem_
    participant ValidateForm
    participant EditContext

    User->>Table: ClickUpdateButtonCallback()
    activate Table
    Table->>ValidateForm: Validate()
    alt validation fails
        ValidateForm-->>Table: false
        Table-->>User: return without saving
    else validation succeeds
        ValidateForm-->>Table: true
        Table->>ValidateForm: GetEditContext()
        alt formless context exists
            ValidateForm-->>Table: EditContext
        else no formless context
            Table->>EditContext: new EditContext(EditModel)
            Note right of EditContext: Created locally in Table
        end
        Table->>Table: SaveAsync(context, changedType)
        Table-->>User: update completed
    end
    deactivate Table
Loading

Class diagram for ValidateForm formless mode and Table in‑cell integration

classDiagram
    class ValidateForm {
        +bool? ShowLabelTooltip
        +bool IsFormless
        -BootstrapBlazorDataAnnotationsValidator Validator
        -EditContext _formlessEditContext
        +void OnParametersSet()
        +bool Validate()
        +EditContext GetEditContext()
        -Task OnValidSubmitForm(EditContext context)
        -Task OnInvalidSubmitForm(EditContext context)
        -Task ValidateObject(ValidationContext context, List~ValidationResult~ results)
        -Dictionary _validatorCache
        -bool _invalid
    }

    class EditContext {
    }

    class Table~TItem~ {
        -bool AddInCell
        -bool EditInCell
        -TItem EditModel
        -IEnumerable~TItem~ SelectedRows
        -bool ShowExtendButtons
        -bool IsExtendButtonsInRowHeader
        -bool InCellMode
        -ValidateForm _inCellValidateForm
        +void ClickEditButton(TItem item)
        +Task ClickUpdateButtonCallback()
        -Task SaveAsync(EditContext context, ItemChangedType changedType)
        -RenderFragment RenderContentRow(TItem item)
        -RenderFragment RenderRowExtendButtons(TItem item)
        -IEnumerable GetVisibleColumns()
    }

    class BootstrapBlazorDataAnnotationsValidator {
    }

    class ItemChangedType {
    }

    ValidateForm --> EditContext : uses
    ValidateForm --> BootstrapBlazorDataAnnotationsValidator : contains
    Table~TItem~ --> ValidateForm : uses _inCellValidateForm
    Table~TItem~ --> EditContext : passes to SaveAsync
    Table~TItem~ --> ItemChangedType : parameter
Loading

Flow diagram for Table row rendering with in‑cell formless validation

flowchart TD
    A[Start row render for item] --> B{"InCellMode && SelectedRows.FirstOrDefault() == item"}
    B -- Yes (in-cell edit row) --> C[Render ValidateForm IsFormless true with Model EditModel]
    C --> D{RowContentTemplate set?}
    D -- Yes --> E[Invoke RowContentTemplate with item, columns, ActiveRenderMode]
    D -- No --> F[RenderContentRow item]
    E --> G{ShowExtendButtons && !IsExtendButtonsInRowHeader}
    F --> G
    G -- Yes --> H[RenderRowExtendButtons item]
    G -- No --> I[Skip extend buttons]
    H --> J[End in-cell row]
    I --> J

    B -- No (normal row) --> K{RowContentTemplate set?}
    K -- Yes --> L[Invoke RowContentTemplate with item, columns, ActiveRenderMode]
    K -- No --> M[RenderContentRow item]
    L --> N{ShowExtendButtons && !IsExtendButtonsInRowHeader}
    M --> N
    N -- Yes --> O[RenderRowExtendButtons item]
    N -- No --> P[Skip extend buttons]
    O --> Q[End normal row]
    P --> Q
Loading

File-Level Changes

Change Details Files
Support a formless validation mode in ValidateForm that exposes an EditContext without rendering a form element.
  • Add IsFormless parameter to toggle between normal form rendering and formless mode.
  • Create and maintain a private EditContext instance when IsFormless is true and a Model is provided.
  • Expose the internal formless EditContext via a new GetEditContext() method.
  • Adjust validation logic so the internal invalid state is updated even when there are no validation components.
  • Branch the razor markup to either render a wrapped EditForm or just cascade the EditContext plus validator based on IsFormless.
src/BootstrapBlazor/Components/ValidateForm/ValidateForm.razor.cs
src/BootstrapBlazor/Components/ValidateForm/ValidateForm.razor
Integrate formless ValidateForm into Table’s in‑cell editing flow to ensure validation and EditContext reuse.
  • Detect when a row is in in‑cell edit mode and wrap that row content in a ValidateForm with IsFormless=true, capturing the instance via @ref.
  • Ensure row content and extend buttons are rendered within the ValidateForm when in in‑cell mode, and preserve existing rendering when not.
  • Store a private _inCellValidateForm reference on the Table component.
  • On update, run validation via _inCellValidateForm.Validate() and bail out on failure, then use the formless EditContext if available when calling SaveAsync.
src/BootstrapBlazor/Components/Table/Table.razor
src/BootstrapBlazor/Components/Table/Table.razor.Toolbar.cs
src/BootstrapBlazor/Components/Table/Table.razor.Edit.cs
Enable validation on auto‑generated in‑cell editor components.
  • Change CreateComponentByFieldType invocation for edit templates to pass skipValidate: false so generated editors participate in validation.
src/BootstrapBlazor/Components/Table/Table.razor.cs

Possibly linked issues

  • #feat(Table): EditMode.InCell Validation: PR adds formless ValidateForm and hooks Table InCell rows to it so validation works as requested.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey - I've left some high level feedback:

  • The in-cell row rendering block in Table.razor now duplicates the RowContentTemplate/RenderContentRow + extend-buttons logic in both the formless and non-formless branches; consider extracting this into a small helper/render fragment to avoid duplication and keep future changes in one place.
  • ValidateForm.GetEditContext() currently returns the private _formlessEditContext but is callable regardless of IsFormless; consider either guarding it so it only returns a non-null context when IsFormless is true or wiring it to the normal EditForm EditContext as well, to avoid confusing nulls or divergent behavior for callers.
  • In the formless ValidateForm markup, _formlessEditContext is cascaded with IsFixed="false" but its lifetime is managed in OnParametersSet; double-check whether it would be cleaner to create/update the EditContext in OnInitialized/OnParametersSet and always cascade a non-null instance to avoid transient null cascades for consumers that rely on EditContext being present.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The in-cell row rendering block in Table.razor now duplicates the RowContentTemplate/RenderContentRow + extend-buttons logic in both the formless and non-formless branches; consider extracting this into a small helper/render fragment to avoid duplication and keep future changes in one place.
- ValidateForm.GetEditContext() currently returns the private _formlessEditContext but is callable regardless of IsFormless; consider either guarding it so it only returns a non-null context when IsFormless is true or wiring it to the normal EditForm EditContext as well, to avoid confusing nulls or divergent behavior for callers.
- In the formless ValidateForm markup, _formlessEditContext is cascaded with IsFixed="false" but its lifetime is managed in OnParametersSet; double-check whether it would be cleaner to create/update the EditContext in OnInitialized/OnParametersSet and always cascade a non-null instance to avoid transient null cascades for consumers that rely on EditContext being present.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@bb-auto bb-auto Bot added the enhancement New feature or request label Dec 28, 2025
@bb-auto bb-auto Bot added this to the v10.1.0 milestone Dec 28, 2025
@codecov
Copy link
Copy Markdown

codecov Bot commented Dec 28, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (814a8c4) to head (c437a92).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #7437   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          749       749           
  Lines        32845     32894   +49     
  Branches      4563      4570    +7     
=========================================
+ Hits         32845     32894   +49     
Flag Coverage Δ
BB 100.00% <100.00%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@celadaris celadaris merged commit f8029af into main Dec 28, 2025
6 checks passed
@celadaris celadaris deleted the EditMode.InCell-Fix branch December 28, 2025 06:09
ArgoZhang added a commit that referenced this pull request Dec 28, 2025
* refactor: 代码重构精简代码逻辑

* refactor: 精简代码

* refactor: 优化性能

* refactor: 消除提示信息

* test: 增加单元测试

* refactor: 更新单元测试

---------

Co-authored-by: Argo Zhang <argo@live.ca>
@ArgoZhang ArgoZhang changed the title Add formless mode to ValidateForm for in-cell table editing feat(Table): support validate InCell Mode Dec 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(Table): EditMode.InCell Validation

2 participants