Reputation: 108
I want to pass a CascadingParameter
to the Counter page component, but I don't want to use the router. Instead of that, I want to use JavaScript because I want the component to be rendered inside the window of Winbox.js (open-source HTML5 window manager).
The problem is that Cascading Parameters are initialized as null
, I think it's happened due to the difference in RenderTree
.
Here is my code:
Registration of Counter.razor
component for JavaScript in Program.cs
:
builder.RootComponents.RegisterForJavaScript<Counter>(identifier: "counter");
For MainLayout.razor
<!-- omitted for brief -->
<CascadingValue Value="_TestCascadingParameter">
<article class="content px-4">
@Body
</article>
</CascadingValue>
<!-- omitted for brief -->
@code{
private TestCascadingParameter _TestCascadingParameter = new() { GlobalCounter = 5 };
public class TestCascadingParameter
{
public int GlobalCounter { get; set; }
}
For Counter page:
@page "/counter"
@using static BlazorApp1.Shared.MainLayout
<PageTitle >Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
[CascadingParameter]
public TestCascadingParameter TestCascadingParameter { get; set; }
private int currentCount = 0;
protected override void OnParametersSet()
{
currentCount = TestCascadingParameter.GlobalCounter;
}
private void IncrementCount()
{
currentCount++;
}
}
For Winbox page:
@page "/WinBox"
@layout MainLayout
@inject IJSRuntime _Js
<PageTitle>Win box</PageTitle>
<button @onclick="@OpenWinAsync">Open window</button>
@code{
async Task OpenWinAsync()
{
await _Js.InvokeVoidAsync("MyWinBox.OpenTestWindow");
}
}
And for MyWinBox.js
:
window.MyWinBox = {
OpenTestWindow: async () => {
let containerElement = new WinBox("WinBox.js");
await Blazor.rootComponents.add(containerElement.body, 'counter', {});
}
};
When I navigate to Counter page using router everything works fine and the currentCount starts from 5, but when I use JavaScript to render it, it throws a NullReferenceException on TestCascadingParameter.
How to solve this without passing Cascading Parameter value through JavaScript because sometimes the Cascading Parameter has a null
value in the caller component as in the above example (eg: if caller component is MudDialog) or sometimes there is more than one Cascading Parameter.
Upvotes: 0
Views: 1273
Reputation: 114
RegisterForJavaScript is new, not well-documented feature and I can't tell if it's possible to pass cascading parameter like that. But I think that you can use State container (or something like Fluxor) to achieve your goals:
public class StateContainer
{
private int? globalCounter;
public int Property
{
get => globalCounter;
set
{
globalCounter = value;
NotifyStateChanged();
}
}
public event Action? OnChange;
private void NotifyStateChanged() => OnChange?.Invoke();
}
More details here: https://learn.microsoft.com/en-us/aspnet/core/blazor/state-management?view=aspnetcore-6.0&pivots=webassembly
Upvotes: 1