Skip to content

Conversation

jHabjanMXP
Copy link
Contributor

@jHabjanMXP jHabjanMXP commented Jul 2, 2025

Issue

[Error] (Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost) Unhandled exception in circuit 'Wvm...'.
Microsoft.JSInterop.JSException: Unable to focus an invalid element.
Error: Unable to focus an invalid element.
    at Object.focus (https://localhost:7039/_framework/blazor.server.js:1:32169)
    at https://localhost:7039/_framework/blazor.server.js:1:2890
    at new Promise (<anonymous>)
    at w.beginInvokeJSFromDotNet (https://localhost:7039/_framework/blazor.server.js:1:2847)
    at Jt._invokeClientMethod (https://localhost:7039/_framework/blazor.server.js:1:63689)
    at Jt._processIncomingData (https://localhost:7039/_framework/blazor.server.js:1:61078)
    at Jt.connection.onreceive (https://localhost:7039/_framework/blazor.server.js:1:54719)
    at i.onmessage (https://localhost:7039/_framework/blazor.server.js:1:78667)
   at Microsoft.JSInterop.JSRuntime.InvokeAsync[TValue](Int64 targetInstanceId, String identifier, Object[] args)
   at Microsoft.JSInterop.JSRuntimeExtensions.InvokeVoidAsync(IJSRuntime jsRuntime, String identifier, Object[] args)
   at MudBlazor.MudFocusTrap.OnAfterRenderAsync(Boolean firstRender)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
2025-07-02 18:25:40.025 +02:00 [Warning] (Microsoft.AspNetCore.Components.Server.Circuits.RemoteRenderer) Unhandled exception rendering component: Unable to focus an invalid element.

Received above issue when opening and closing dialog fast multiple times.

Changes

  • using disposed check, not to start JsInterop processes in SaveFocusAsync and InitializeFocusAsync AFTER the component has already been disposed of

Type of Changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation (fix or improvement to the website or code docs)

Checklist

  • The PR is submitted to the correct branch (dev).
  • My code follows the code style of this project.
  • I've added relevant tests.

## Changes
- Catching possible exceptions in MudFocusTrap.OnAfterRenderAsync which are thrown by JSInterop
@github-actions github-actions bot added the bug Unexpected behavior or functionality not working as intended label Jul 2, 2025
Copy link
Member

@danielchalmers danielchalmers left a comment

Choose a reason for hiding this comment

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

Is it possible to catch a more specific exception than Exception?

Copilot

This comment was marked as outdated.

Copy link
Contributor

@versile2 versile2 left a comment

Choose a reason for hiding this comment

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

I would prefer to see if (_disposed) return; statements than a bunch of try/catch exceptions. Did you try that?

@jHabjanMXP
Copy link
Contributor Author

will try thanks

@versile2
Copy link
Contributor

Any update on this?

jHabjanMXP and others added 2 commits July 11, 2025 16:49
## Changes
- Removing the try-catch from 341d6fa
- using `disposed` check, not to start JsInterop processes in SaveFocusAsync and InitializeFocusAsync AFTER the component has already been disposed of
@jHabjanMXP
Copy link
Contributor Author

@versile2 I adjusted the solution

Copy link

Copy link

codecov bot commented Jul 11, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 91.31%. Comparing base (ad0a8c8) to head (1108eb4).
Report is 15 commits behind head on dev.

Additional details and impacted files
@@           Coverage Diff           @@
##              dev   #11586   +/-   ##
=======================================
  Coverage   91.31%   91.31%           
=======================================
  Files         466      466           
  Lines       14707    14708    +1     
  Branches     2857     2857           
=======================================
+ Hits        13430    13431    +1     
  Misses        635      635           
  Partials      642      642           

☔ 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.

@versile2
Copy link
Contributor

@versile2 I adjusted the solution

Did this _isDisposed solve the problem like your other solution?

@versile2 versile2 requested a review from Copilot July 11, 2025 15:34
Copy link
Contributor

@Copilot 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 a disposal guard to MudFocusTrap to prevent JS interop calls after the component has been disposed, avoiding JS exceptions when rapidly opening and closing dialogs.

  • Introduces a _disposed flag in the component.
  • Adds an early-exit check in OnAfterRenderAsync to skip focus/save operations if disposed.
  • Sets _disposed to true in Dispose before calling RestoreFocusAsync.
Comments suppressed due to low confidence (2)

src/MudBlazor/Components/FocusTrap/MudFocusTrap.razor.cs:21

  • [nitpick] Consider renaming the field _disposed to _isDisposed or _hasBeenDisposed to more explicitly convey its boolean semantics and align with common naming conventions.
        private bool _disposed;

src/MudBlazor/Components/FocusTrap/MudFocusTrap.razor.cs:80

  • Add unit or integration tests to simulate quick open/close scenarios, ensuring that no JS Interop calls are made after the component has been disposed to verify this new guard logic.
            if (_disposed) return;

@danielchalmers danielchalmers changed the title MudFocusTrap: Wrap JS calls in try-catch MudFocusTrap: Prevent JSException on Disposed Component Jul 12, 2025
@jHabjanMXP
Copy link
Contributor Author

Yes, it prevents the component from crashing by preventing code being executed after the component is destroyed

@versile2
Copy link
Contributor

@danielchalmers @ScarletKuro This is ready to merge, super simple now.

@danielchalmers danielchalmers merged commit ec211d9 into MudBlazor:dev Jul 14, 2025
6 checks passed
@danielchalmers
Copy link
Member

Thank you!

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

Labels

bug Unexpected behavior or functionality not working as intended

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants