Skip to content

fix(AutoComplete): shoud trigger ValueChanged after enter#7281

Merged
ArgoZhang merged 1 commit intomainfrom
fix-auto
Dec 9, 2025
Merged

fix(AutoComplete): shoud trigger ValueChanged after enter#7281
ArgoZhang merged 1 commit intomainfrom
fix-auto

Conversation

@ArgoZhang
Copy link
Copy Markdown
Member

@ArgoZhang ArgoZhang commented Dec 9, 2025

Link issues

fixes #7270

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

Bug Fixes:

  • Fix AutoComplete so that pressing Enter always invokes the value change callback after any pending item click is processed.

Copilot AI review requested due to automatic review settings December 9, 2025 08:00
@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented Dec 9, 2025

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Adjusts AutoComplete Enter key handling to click the active/only item and then trigger EnterCallback asynchronously, ensuring ValueChanged fires correctly before the callback executes.

Sequence diagram for AutoComplete Enter key handling and ValueChanged order

sequenceDiagram
    actor User
    participant AutoCompleteInput
    participant AutoCompleteMenu
    participant ActiveItem
    participant JsTimeout
    participant BlazorInterop
    participant DotNetComponent

    User->>AutoCompleteInput: keydown Enter
    AutoCompleteInput->>AutoCompleteInput: handlerKeydown
    AutoCompleteInput->>AutoCompleteInput: read data-bb-skip-enter
    alt skip_enter_true
        AutoCompleteInput-->>User: ignore Enter
    else skip_enter_false
        AutoCompleteInput->>AutoCompleteMenu: querySelectorAll .dropdown-item
        AutoCompleteMenu-->>AutoCompleteInput: items
        alt single_item
            AutoCompleteInput->>AutoCompleteInput: set activeItem = items[0]
        else multiple_items
            AutoCompleteInput->>AutoCompleteMenu: querySelector .active
            AutoCompleteMenu-->>AutoCompleteInput: activeItem
        end
        AutoCompleteInput->>JsTimeout: setTimeout 0ms
        JsTimeout-->>AutoCompleteInput: timeout callback
        alt activeItem_not_null
            AutoCompleteInput->>ActiveItem: click()
            ActiveItem->>BlazorInterop: invoke ValueChanged via click handler
            BlazorInterop->>DotNetComponent: ValueChanged
            DotNetComponent-->>BlazorInterop: state updated
        else activeItem_null
            AutoCompleteInput-->>User: no item clicked
        end
        AutoCompleteInput->>BlazorInterop: invokeMethodAsync EnterCallback
        BlazorInterop->>DotNetComponent: EnterCallback
        DotNetComponent-->>User: handle Enter after ValueChanged
    end
Loading

Flow diagram for updated handlerKeydown Enter logic

flowchart TD
    A_start[Start handlerKeydown on Enter] --> B_checkSkip[Read data-bb-skip-enter]
    B_checkSkip -->|true| Z_end[End handlerKeydown]
    B_checkSkip -->|false| C_getItems[Query .dropdown-item items]
    C_getItems --> D_itemsCount{items length == 1}
    D_itemsCount -->|yes| E_setActiveItemSingle[Set activeItem = items at index 0]
    D_itemsCount -->|no| F_findActive[Set activeItem = menu.querySelector .active]
    E_setActiveItemSingle --> G_setTimeout[setTimeout 0ms]
    F_findActive --> G_setTimeout
    G_setTimeout --> H_timeoutCallback[Timeout callback executes]
    H_timeoutCallback --> I_activeItemCheck{activeItem is not null}
    I_activeItemCheck -->|yes| J_clickActiveItem[activeItem.click]
    I_activeItemCheck -->|no| K_skipClick[Skip item click]
    J_clickActiveItem --> L_valueChanged[Item click triggers ValueChanged]
    L_valueChanged --> M_enterCallback[invokeMethodAsync EnterCallback]
    K_skipClick --> M_enterCallback
    M_enterCallback --> Z_end
Loading

File-Level Changes

Change Details Files
Change Enter-key handling in AutoComplete so the active or single dropdown item is clicked before EnterCallback is invoked, using an async timeout to ensure proper event ordering.
  • Capture the single available item or the currently active dropdown item instead of clicking it immediately on Enter.
  • Wrap item click and EnterCallback invocation in a zero-delay setTimeout handler to defer execution.
  • Ensure the captured item is clicked if present, then invoke EnterCallback asynchronously via invokeMethodAsync.
src/BootstrapBlazor/Components/AutoComplete/AutoComplete.razor.js

Assessment against linked issues

Issue Objective Addressed Explanation
#7270 Ensure that when selecting an option in AutoComplete using Up/Down arrows plus Enter, the value change logic is triggered only once instead of twice.
#7270 Ensure that when selecting an option in AutoComplete using Up/Down arrows plus Enter, the final displayed value in the input matches the actual bound value (@bind-Value).

Possibly linked issues


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

@bb-auto bb-auto Bot added the bug Something isn't working label Dec 9, 2025
@bb-auto bb-auto Bot added this to the v10.1.0 milestone Dec 9, 2025
@ArgoZhang ArgoZhang merged commit ee29501 into main Dec 9, 2025
7 of 8 checks passed
@ArgoZhang ArgoZhang deleted the fix-auto branch December 9, 2025 08:00
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 there - I've reviewed your changes - here's some feedback:

  • The setTimeout callback clears its own timer (clearTimeout(handler)), which is redundant once the handler is already executing and can be safely removed to simplify the code.
  • Consider adding a brief comment explaining why setTimeout(..., 0) is needed before invoking EnterCallback, so future readers understand the ordering requirement between the item click and the callback.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The `setTimeout` callback clears its own timer (`clearTimeout(handler)`), which is redundant once the handler is already executing and can be safely removed to simplify the code.
- Consider adding a brief comment explaining why `setTimeout(..., 0)` is needed before invoking `EnterCallback`, so future readers understand the ordering requirement between the item click and the callback.

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.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes an issue where the AutoComplete component's ValueChanged event was not being triggered after pressing Enter. The fix ensures that when Enter is pressed on an autocomplete item, the item click handler executes before the EnterCallback is invoked, allowing the value to be properly updated.

Key changes:

  • Refactored Enter key handling to consolidate active item detection logic
  • Introduced a setTimeout wrapper to defer EnterCallback execution, ensuring the item click completes first

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

invoke.invokeMethodAsync('EnterCallback');

const handler = setTimeout(async () => {
clearTimeout(handler);
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

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

The clearTimeout(handler) is called immediately after setting the timeout, which cancels the timeout before it can execute. This line should be removed as it defeats the purpose of using setTimeout. The timeout will complete on its own and doesn't need to be cleared here.

Suggested change
clearTimeout(handler);

Copilot uses AI. Check for mistakes.
Comment on lines +167 to +170
if (activeItem !== null) {
activeItem.click();
}
await invoke.invokeMethodAsync('EnterCallback');
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

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

The setTimeout callback is defined as async but the returned promise is not handled. If EnterCallback throws an error, it will result in an unhandled promise rejection. Consider either removing the async keyword (if EnterCallback doesn't need to be awaited for the fix to work) or wrap the code in a try-catch block to handle potential errors.

Suggested change
if (activeItem !== null) {
activeItem.click();
}
await invoke.invokeMethodAsync('EnterCallback');
try {
if (activeItem !== null) {
activeItem.click();
}
await invoke.invokeMethodAsync('EnterCallback');
} catch (error) {
// Optionally log the error or handle it as needed
console.error('Error in EnterCallback:', error);
}

Copilot uses AI. Check for mistakes.
@codecov
Copy link
Copy Markdown

codecov Bot commented Dec 9, 2025

Codecov Report

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

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #7281   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          745       745           
  Lines        32628     32628           
  Branches      4522      4522           
=========================================
  Hits         32628     32628           
Flag Coverage Δ
BB 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.

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.

bug(AutoComplete): OnValueChanged triggered twice with wrong value

2 participants