Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions BlazorSortableList.Lib/SortableList.razor
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

@inject IJSRuntime JS

@implements IAsyncDisposable

@typeparam T

<div id="@Id" style ="@Style">
Expand Down
50 changes: 46 additions & 4 deletions BlazorSortableList.Lib/SortableList.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ public partial class SortableList<T>

private DotNetObjectReference<SortableList<T>>? selfReference;

private IJSObjectReference? _module;

/// <summary>
/// The id the JS instance was registered under. <see cref="Id"/> is a mutable parameter, so it
/// cannot be trusted to still hold the key the instance is stored against by disposal time.
/// </summary>
private string? _initializedId;

private string _cssForSelection;

private string? _multiDragKey = string.Empty;
Expand Down Expand Up @@ -68,7 +76,40 @@ public partial class SortableList<T>
[Parameter]
public RenderFragment<T>? SortableItemTemplate { get; set; }

public void Dispose() => selfReference?.Dispose();
public async ValueTask DisposeAsync()
{
try
{
if (_module != null)
{
try
{
if (_initializedId != null)
{
await _module.InvokeVoidAsync("destroy", _initializedId);
}
}
finally
{
await _module.DisposeAsync();
}
}
}
catch (JSDisconnectedException)
{
// The circuit is already gone, so there is nothing left to clean up on the JS side.
}
catch (JSException)
{
// A failing teardown on the JS side must not stop the managed references from being released.
}
finally
{
_module = null;
selfReference?.Dispose();
selfReference = null;
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

[JSInvokable]
public void OnDeselectJS(string fromId, int index)
Expand Down Expand Up @@ -146,12 +187,13 @@ protected override async Task OnAfterRenderAsync(bool firstRender)
if (firstRender)
{
selfReference = DotNetObjectReference.Create(this);
var module = await JS.InvokeAsync<IJSObjectReference>("import", "./_content/BlazorSortableList/SortableList.razor.js");
_module = await JS.InvokeAsync<IJSObjectReference>("import", "./_content/BlazorSortableList/SortableList.razor.js");

//await JS.InvokeVoidAsync("console.log", $"***id:{Id}, group:{Group},pull: {Pull},put:{Put},sort:{Sort}, handle:{Handle}, filter:{Filter}, forceFallback:{ForceFallback}");
await module.InvokeAsync<string>(
_initializedId = Id;
await _module.InvokeVoidAsync(
"init",
Id,
_initializedId,
Group,
Pull,
Put,
Expand Down
15 changes: 15 additions & 0 deletions BlazorSortableList.Lib/SortableList.razor.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
const instances = new Map();

export function destroy(id) {
const sortable = instances.get(id);
if (sortable) {
sortable.destroy();
instances.delete(id);
}
}

export function init(id, group, pull, put, sort, handle, filter, component, forceFallback, cssForSelection, multiDragKey, avoidImplicitDeselect, fallbackOnBody, swapThreshold) {

const DEBUG_MODE = true;
Expand Down Expand Up @@ -51,6 +61,9 @@ export function init(id, group, pull, put, sort, handle, filter, component, forc
// }
// });

// A component re-initialising under an id we already track would otherwise orphan the previous instance.
destroy(id);

var sortable = new SortableCtor(htmlElement, {
animation: 200,
group: {
Expand Down Expand Up @@ -187,4 +200,6 @@ export function init(id, group, pull, put, sort, handle, filter, component, forc
}
}
});

instances.set(id, sortable);
}