Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 15, 2025

Add cancel event support to InputFile component

  • You've read the Contributor Guide and Code of Conduct.
  • You've included unit or integration tests for your change, where applicable.
  • You've included inline docs for your change, where applicable.
  • There's an open issue for the PR that you are making. If you'd like to propose a new feature or change, please open an issue to discuss the change or find an existing issue.

Subscribe to HTML5 cancel event to clear InputFile state

Description

When users click an InputFile, select a file, then click again and cancel the dialog, the browser clears the input but OnChange is not invoked, leaving application state out of sync.

Changes

JavaScript (InputFile.ts)

  • Added cancel event listener that invokes NotifyChange with empty array
  • Clears internal file cache on cancel

E2E Tests (InputFileTest.cs)

  • Added test that dispatches cancel event and verifies file list clears
  • Added file count element to test component for verification

Browser Compatibility

  • Cancel event is HTML5 standard, supported in modern browsers
  • Graceful degradation in older browsers (listener ignored)

Example

<InputFile OnChange="HandleFiles" />

@code {
    void HandleFiles(InputFileChangeEventArgs e)
    {
        // Now invoked with FileCount=0 when user cancels dialog
        Console.WriteLine($"Files selected: {e.FileCount}");
    }
}

Fixes #49148

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • accounts.google.com
    • Triggering command: /proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --no-sandbox --ignore-certificate-errors --use-angle=swiftshader-webgl --ignore-certificate-errors --crashpad-handler-pid=8847 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/.org.chromium.Chromium.scoped_dir.aXmDxz --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,11065873433458544356,1928737019256929910,262144 --disable-features=IgnoreDuplicateNavs,PaintHolding,Prewarm --variations-seed-version --trace-process-track-uuid=3190708989122997041 --enable-logging=stderr (dns block)
    • Triggering command: /opt/google/chrome/chrome /opt/google/chrome/chrome --allow-pre-commit-input --disable-REDACTED-networking --disable-client-side-phishing-detection --disable-default-apps --disable-features=IgnoreDuplicateNavs,Prewarm --disable-hang-monitor --disable-popup-blocking --disable-prompt-on-repost --disable-sync --enable-automation --enable-logging=stderr --headless=new --ignore-certificate-errors --log-level=0 --no-first-run --no-sandbox --no-service-autorun --password-store=basic --remote-debugging-port=0 (dns block)
    • Triggering command: /proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --no-sandbox --ignore-certificate-errors --use-angle=swiftshader-webgl --ignore-certificate-errors --crashpad-handler-pid=8978 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/.org.chromium.Chromium.scoped_dir.bWIE5N --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,10514598102542772605,13464673224335845380,262144 --disable-features=IgnoreDuplicateNavs,PaintHolding,Prewarm --variations-seed-version --trace-process-track-uuid=3190708989122997041 --enable-logging=stderr (dns block)
  • clients2.google.com
    • Triggering command: /proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --no-sandbox --ignore-certificate-errors --use-angle=swiftshader-webgl --ignore-certificate-errors --crashpad-handler-pid=8847 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/.org.chromium.Chromium.scoped_dir.aXmDxz --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,11065873433458544356,1928737019256929910,262144 --disable-features=IgnoreDuplicateNavs,PaintHolding,Prewarm --variations-seed-version --trace-process-track-uuid=3190708989122997041 --enable-logging=stderr (dns block)
    • Triggering command: /opt/google/chrome/chrome /opt/google/chrome/chrome --allow-pre-commit-input --disable-REDACTED-networking --disable-client-side-phishing-detection --disable-default-apps --disable-features=IgnoreDuplicateNavs,Prewarm --disable-hang-monitor --disable-popup-blocking --disable-prompt-on-repost --disable-sync --enable-automation --enable-logging=stderr --headless=new --ignore-certificate-errors --log-level=0 --no-first-run --no-sandbox --no-service-autorun --password-store=basic --remote-debugging-port=0 (dns block)
    • Triggering command: /proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --no-sandbox --ignore-certificate-errors --use-angle=swiftshader-webgl --ignore-certificate-errors --crashpad-handler-pid=8978 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/.org.chromium.Chromium.scoped_dir.bWIE5N --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,10514598102542772605,13464673224335845380,262144 --disable-features=IgnoreDuplicateNavs,PaintHolding,Prewarm --variations-seed-version --trace-process-track-uuid=3190708989122997041 --enable-logging=stderr (dns block)
  • content-autofill.googleapis.com
    • Triggering command: /proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --no-sandbox --ignore-certificate-errors --use-angle=swiftshader-webgl --ignore-certificate-errors --crashpad-handler-pid=8847 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/.org.chromium.Chromium.scoped_dir.aXmDxz --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,11065873433458544356,1928737019256929910,262144 --disable-features=IgnoreDuplicateNavs,PaintHolding,Prewarm --variations-seed-version --trace-process-track-uuid=3190708989122997041 --enable-logging=stderr (dns block)
    • Triggering command: /opt/google/chrome/chrome /opt/google/chrome/chrome --allow-pre-commit-input --disable-REDACTED-networking --disable-client-side-phishing-detection --disable-default-apps --disable-features=IgnoreDuplicateNavs,Prewarm --disable-hang-monitor --disable-popup-blocking --disable-prompt-on-repost --disable-sync --enable-automation --enable-logging=stderr --headless=new --ignore-certificate-errors --log-level=0 --no-first-run --no-sandbox --no-service-autorun --password-store=basic --remote-debugging-port=0 (dns block)
    • Triggering command: /proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --no-sandbox --ignore-certificate-errors --use-angle=swiftshader-webgl --ignore-certificate-errors --crashpad-handler-pid=8978 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/.org.chromium.Chromium.scoped_dir.bWIE5N --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,10514598102542772605,13464673224335845380,262144 --disable-features=IgnoreDuplicateNavs,PaintHolding,Prewarm --variations-seed-version --trace-process-track-uuid=3190708989122997041 --enable-logging=stderr (dns block)
  • optimizationguide-pa.googleapis.com
    • Triggering command: /proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --no-sandbox --ignore-certificate-errors --use-angle=swiftshader-webgl --ignore-certificate-errors --crashpad-handler-pid=9535 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/.org.chromium.Chromium.scoped_dir.5ug3h2 --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,15083003803038379771,12943745612694853865,262144 --disable-features=IgnoreDuplicateNavs,PaintHolding,Prewarm --variations-seed-version --trace-process-track-uuid=3190708989122997041 --enable-logging=stderr (dns block)
    • Triggering command: /opt/google/chrome/chrome /opt/google/chrome/chrome --allow-pre-commit-input --disable-REDACTED-networking --disable-client-side-phishing-detection --disable-default-apps --disable-features=IgnoreDuplicateNavs,Prewarm --disable-hang-monitor --disable-popup-blocking --disable-prompt-on-repost --disable-sync --enable-automation --enable-logging=stderr --headless=new --ignore-certificate-errors --log-level=0 --no-first-run --no-sandbox --no-service-autorun --password-store=basic --remote-debugging-port=0 (dns block)
    • Triggering command: /proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --no-sandbox --ignore-certificate-errors --use-angle=swiftshader-webgl --ignore-certificate-errors --crashpad-handler-pid=11796 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/.org.chromium.Chromium.scoped_dir.V4TEB2 --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,3660359013470927173,13435652235128586101,262144 --disable-features=IgnoreDuplicateNavs,PaintHolding,Prewarm --variations-seed-version --trace-process-track-uuid=3190708989122997041 --enable-logging=stderr (dns block)
  • www.google.com
    • Triggering command: /proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --no-sandbox --ignore-certificate-errors --use-angle=swiftshader-webgl --ignore-certificate-errors --crashpad-handler-pid=8847 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/.org.chromium.Chromium.scoped_dir.aXmDxz --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,11065873433458544356,1928737019256929910,262144 --disable-features=IgnoreDuplicateNavs,PaintHolding,Prewarm --variations-seed-version --trace-process-track-uuid=3190708989122997041 --enable-logging=stderr (dns block)
    • Triggering command: /opt/google/chrome/chrome /opt/google/chrome/chrome --allow-pre-commit-input --disable-REDACTED-networking --disable-client-side-phishing-detection --disable-default-apps --disable-features=IgnoreDuplicateNavs,Prewarm --disable-hang-monitor --disable-popup-blocking --disable-prompt-on-repost --disable-sync --enable-automation --enable-logging=stderr --headless=new --ignore-certificate-errors --log-level=0 --no-first-run --no-sandbox --no-service-autorun --password-store=basic --remote-debugging-port=0 (dns block)
    • Triggering command: /proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --no-sandbox --ignore-certificate-errors --use-angle=swiftshader-webgl --ignore-certificate-errors --crashpad-handler-pid=8978 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/.org.chromium.Chromium.scoped_dir.bWIE5N --change-stack-guard-on-fork=enable --shared-files=v8_context_snapshot_data:100 --field-trial-handle=3,i,10514598102542772605,13464673224335845380,262144 --disable-features=IgnoreDuplicateNavs,PaintHolding,Prewarm --variations-seed-version --trace-process-track-uuid=3190708989122997041 --enable-logging=stderr (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>[Blazor] InputFile support for cancel event</issue_title>
<issue_description>### Is there an existing issue for this?

  • I have searched the existing issues

Is your feature request related to a problem? Please describe the problem.

Currently, InputFile does not handle the cancel event in this scenario (#49148):

  1. Click on the file input.
  2. Select a file. OnChange will be invoked.
  3. Click on the file input again.
  4. Click "Cancel" in the file selection window. The file input will be cleared, but OnChange will not be invoked, so the app still thinks a file is selected.

There hasn't been a way to handle this, as there was no signal from the browser about the dialog being canceled. However, there is now a cancel event that can be used.

Describe the solution you'd like

I would like to subscribe to the cancel event of the underlying <input type="file"> and invoke OnChange.Invoke(new()) with an empty list of files.

Additional context

Related issue: havit/Havit.Blazor#884
Related discussion: https://stackoverflow.com/a/76926836/4150304</issue_description>

<agent_instructions>Prepare a PR for this. Look at the E2E tests for InputFile and make sure to add coverage for this case.</agent_instructions>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 2 commits December 15, 2025 14:10
Co-authored-by: javiercn <6995051+javiercn@users.noreply.github.com>
Co-authored-by: javiercn <6995051+javiercn@users.noreply.github.com>
Copilot AI changed the title [WIP] Add InputFile support for cancel event Add cancel event support to InputFile component Dec 15, 2025
Copilot AI requested a review from javiercn December 15, 2025 14:23
@javiercn javiercn marked this pull request as ready for review December 17, 2025 14:04
@javiercn javiercn requested a review from a team as a code owner December 17, 2025 14:04
Copilot AI review requested due to automatic review settings December 17, 2025 14:04
Copy link
Member

@maraf maraf left a comment

Choose a reason for hiding this comment

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

Looks good to me 👍

Copy link
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 adds support for the HTML5 cancel event to the InputFile component, addressing a state synchronization issue where canceling the file picker dialog doesn't notify the application. When users select a file, click the input again, and cancel the dialog, the browser clears the input but the application state remains out of sync. This change ensures the component's state is properly cleared when the cancel event fires.

Key Changes:

  • Added cancel event listener in TypeScript that invokes NotifyChange with an empty file array
  • Added E2E test to verify file state is cleared when cancel event is dispatched
  • Added file count display element to test component for verification

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
src/Components/Web.JS/src/InputFile.ts Adds cancel event listener that clears internal file cache and notifies with empty file list
src/Components/test/E2ETest/Tests/InputFileTest.cs Adds E2E test verifying that cancel event clears file selection state
src/Components/test/testassets/BasicTestApp/FormsTest/InputFileComponent.razor Adds file count span element for test verification

@javiercn javiercn merged commit 870c9d6 into main Dec 17, 2025
32 of 33 checks passed
@javiercn javiercn deleted the copilot/add-inputfile-cancel-event-support branch December 17, 2025 14:22
@dotnet-policy-service dotnet-policy-service bot added this to the 11.0-preview1 milestone Dec 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Blazor] InputFile support for cancel event Blazor WASM InputFile OnChange doesnt invoke when input file is no longer selected

4 participants