Reputation: 81
so...Im working on a Blazor Server app and having troubles with anderstanding of how a cascading parameters work and why my MainLayout returns always null.
Im doing it like this: MainLayout.razor:
<CascadingValue Value="this">
<PageTitle>Global</PageTitle>
<div id="wrapper">
<SfToolbar CssClass="dockToolbar">
<ToolbarEvents Clicked="@Toggle"></ToolbarEvents>
<ToolbarItems>
<ToolbarItem PrefixIcon="e-icons e-menu" TooltipText="Menu"></ToolbarItem>
<ToolbarItem>
<Template>
<div class="e-folder">
<div class="e-folder-name">Global</div>
</div>
</Template>
</ToolbarItem>
</ToolbarItems>
</SfToolbar>
<div id="main-content container-fluid col-md-12" class="maincontent">
<div>
<div class="content">@Body</div>
</div>
</div>
</div>
and Pages that behaves
SignIn.razor:
@page "/sign-in"
<ComponentLibrary.Components.AuthPage backUrl="/"></ComponentLibrary.Components.AuthPage>
@code {
[CascadingParameter]
public MainLayout? Layout { get; set; }
protected override void OnInitialized()
{
Layout.userModel = null;
Layout.RefreshSideBar();
base.OnInitialized();
}
}
But when im getting on SignIn page my Layout for some reason is null, any advices where need to look at?
i tried to just create a new example of Layout in other pages but that is tottaly not what i needed
Upvotes: 1
Views: 1244
Reputation: 30001
So let's try and recreate your problem.
Start with a standard Blazor server project.
@inherits LayoutComponentBase
<PageTitle>SO74799583</PageTitle>
<CascadingValue Value=this>
<div class="page">
<div class="sidebar">
<NavMenu />
</div>
<main>
<div class="top-row px-4">
<a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
</div>
<article class="content px-4">
@Body
</article>
</main>
</div>
</CascadingValue>
@code {
public string RenderTime = DateTime.Now.ToLongTimeString();
protected override bool ShouldRender()
{
RenderTime = DateTime.Now.ToLongTimeString();
return true;
}
}
And Index:
@page "/"
<PageTitle>Index</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.
<SurveyPrompt Title="How is Blazor working for you?" />
<div class="bg-dark text-white p-2 m-2">
Main Component last rendered at: @(this.mainLayout?.RenderTime ?? "Not Rendered")
</div>
@code {
[CascadingParameter] private MainLayout? mainLayout { get; set; }
}
Which works: mainLayout
is not null. So your not showing us everything.
Note that it's not normally a good idea to cascade or pass around a reference to a Component.
If you want to communicate between components create a state class and either:
Here's a simple example.
public class MyState
{
public string LastUpdateTime { get; private set; } = "Not Set";
public event EventHandler<string>? Updated;
public void SetTime()
{
this.LastUpdateTime = DateTime.Now.ToLongTimeString();
this.Updated?.Invoke(this, this.LastUpdateTime);
}
}
Layout:
@inherits LayoutComponentBase
<PageTitle>SO74799583</PageTitle>
<CascadingValue Value=myState>
<div class="page">
<div class="sidebar">
<NavMenu />
</div>
<main>
<div class="top-row px-4">
<a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
</div>
<article class="content px-4">
<div class="alert alert-info">@RenderTime</div>
@Body
</article>
</main>
</div>
</CascadingValue>
@code {
public string RenderTime = DateTime.Now.ToLongTimeString();
private MyState myState = new();
protected override void OnInitialized()
=> myState.Updated += OnUpdated;
private void OnUpdated(object? sender, string value)
=> StateHasChanged();
public void Dispose()
=> myState.Updated -= OnUpdated;
}
And Index:
@page "/"
<PageTitle>Index</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.
<div class="p-2 m-2">
<button class="btn btn-primary" @onclick=Update>Update Time</button>
</div>
@code {
[CascadingParameter] private MyState? myState { get; set; }
private Task Update()
{
myState?.SetTime();
return Task.CompletedTask;
}
}
Upvotes: 1
Reputation: 81
Yes, you guys were right. I just noticed that there was 2 MainLayout files i miss that part, sorry. removing from project extra layout solves the problem
Upvotes: 1