diff --git a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml
index 9e011ef08d..19a770feef 100644
--- a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml
+++ b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml
@@ -9127,6 +9127,9 @@
+
+
+
Gets or sets the template to be used to define each sortable item in the list.
diff --git a/src/Core/Components/SortableList/FluentSortableList.razor.cs b/src/Core/Components/SortableList/FluentSortableList.razor.cs
index 031cd64f18..e3dfaf363d 100644
--- a/src/Core/Components/SortableList/FluentSortableList.razor.cs
+++ b/src/Core/Components/SortableList/FluentSortableList.razor.cs
@@ -10,10 +10,11 @@
namespace Microsoft.FluentUI.AspNetCore.Components;
-public partial class FluentSortableList : FluentComponentBase
+public partial class FluentSortableList : FluentComponentBase, IAsyncDisposable
{
private const string JAVASCRIPT_FILE = "./_content/Microsoft.FluentUI.AspNetCore.Components/Components/SortableList/FluentSortableList.razor.js";
private DotNetObjectReference>? _selfReference;
+ private bool _disposed;
///
[Inject]
@@ -23,6 +24,9 @@ public partial class FluentSortableList : FluentComponentBase
[Inject]
private IJSRuntime JSRuntime { get; set; } = default!;
+ ///
+ private IJSObjectReference? Module { get; set; }
+
///
/// Gets or sets the template to be used to define each sortable item in the list.
/// Use the @context parameter to access the item and its properties.
@@ -190,21 +194,16 @@ public partial class FluentSortableList : FluentComponentBase
protected override async Task OnAfterRenderAsync(bool firstRender)
{
- try
+
+ if (firstRender)
{
- if (firstRender)
+ _selfReference = DotNetObjectReference.Create(this);
+ Module = await JSRuntime.InvokeAsync("import", JAVASCRIPT_FILE.FormatCollocatedUrl(LibraryConfiguration));
+ if (!_disposed)
{
- _selfReference = DotNetObjectReference.Create(this);
- IJSObjectReference? module = await JSRuntime.InvokeAsync("import", JAVASCRIPT_FILE.FormatCollocatedUrl(LibraryConfiguration));
- await module.InvokeAsync("init", Element, Group, Clone ? "clone" : null, Drop, Sort, Handle ? ".sortable-grab" : null, Filter, Fallback, _selfReference);
+ await Module.InvokeAsync("init", Element, Group, Clone ? "clone" : null, Drop, Sort, Handle ? ".sortable-grab" : null, Filter, Fallback, _selfReference);
}
}
- catch (Exception ex) when (ex is JSDisconnectedException ||
- ex is OperationCanceledException)
- {
- // This exception is expected when the user navigates away from the page
- // and the component is disposed. We can ignore it.
- }
}
protected bool GetItemFiltered(TItem item)
@@ -239,5 +238,27 @@ public void OnRemoveJS(int oldIndex, int newIndex, string fromListId, string toL
}
}
- public void Dispose() => _selfReference?.Dispose();
+ public async ValueTask DisposeAsync()
+ {
+ if (_disposed)
+ {
+ return;
+ }
+
+ try
+ {
+ _selfReference?.Dispose();
+ _disposed = true;
+ if (Module is not null)
+ {
+ await Module.DisposeAsync();
+ }
+ }
+ catch (Exception ex) when (ex is JSDisconnectedException ||
+ ex is OperationCanceledException)
+ {
+ // The JSRuntime side may routinely be gone already if the reason we're disposing is that
+ // the client disconnected. This is not an error.
+ }
+ }
}