@inject IJSRuntime JS @implements IAsyncDisposable
@if (_isRendering) {
rendering diagram…
} else if (_error is not null) {
@_error
}
@code { [Parameter] public string? Source { get; set; } [Parameter] public string? TestId { get; set; } /// /// The id of the host element holding the rendered SVG. Defaults to a /// random GUID per instance; pages that need to call SVG-export JS on /// this view should pass a stable id. /// [Parameter] public string? Id { get; set; } private string HostId => Id ?? _generatedId; private readonly string _generatedId = $"rpkg-host-{Guid.NewGuid():N}"; private string? _renderedSource; private bool _isRendering; private string? _error; protected override async Task OnAfterRenderAsync(bool firstRender) { // Re-render only when the source actually changes — Blazor calls // OnAfterRender on every state change. if (Source == _renderedSource) return; _renderedSource = Source; if (string.IsNullOrWhiteSpace(Source)) { try { await JS.InvokeVoidAsync("rackpeekGraph.render", HostId, ""); } catch { // Ignore — the host may not be ready / the page is unloading. } return; } _isRendering = true; _error = null; StateHasChanged(); try { await JS.InvokeVoidAsync("rackpeekGraph.render", HostId, Source); } catch (Exception ex) { _error = $"Diagram render failed: {ex.Message}"; } finally { _isRendering = false; StateHasChanged(); } } public async ValueTask DisposeAsync() { try { await JS.InvokeVoidAsync("rackpeekGraph.render", HostId, ""); } catch { // ignore on teardown } } }