Guy Lowe
Guy Lowe

Reputation: 2370

Passing values from Blazor layout to Page

I'm trying to pass values from a select control on a blazor layout as they change to the current page. i.e. I have a dropdown that when the values is changed it needs to tell the page (via an event, parameter or cascasding parameter I'm not sure):

So far I have this:

_layout.razor

<div class="page">
     <select onchange="OnSiteChanged">
         <option value="1">Site 1</option>
         <option value="2">Site 2</option>
     </select>
</div>

@code{
    [Parameter]
    public EventHandler SiteChanged{ get; set; }

     private void OnSiteChanged(object sender, EventArgs e)
     {
         SiteChanged.Invoke(this, e);
     }
}

and pass it to the underlying page:

pagewithlayout.razor

@code{
    [Parameter]
    public EventCallback SiteChanged { get; set; }

     public async Task OnSiteChanged(EventArgs e){
         /do something
     }
}

However the event on the page never fires. Any ideas?

Upvotes: 1

Views: 988

Answers (1)

Guy Lowe
Guy Lowe

Reputation: 2370

Thanks for @JeremyLakeman for the help that lead to this answer. This answer is specific to layouts publishing data to their pages.

Notification Service

First, I had to create a service to encapsulate the event:

public class NotifiySiteChangedService
{
    public EventHandler? SiteChanged;

    public void OnSiteChanged(object sender, SiteIdChangeEventArgs e)
    {
        if (this.SiteChanged != null)
        {
            this.SiteChanged(this, e);
        }
    }
}

public class SiteIdChangeEventArgs : EventArgs
{
    public int SiteId { get; set; }

    public SiteIdChangeEventArgs(int siteId) : base()
    {
        SiteId = siteId;
    }
}

Program.cs

Then to make it available in the app I had to register it in Program.cs:

builder.Services.AddScoped<NotifiySiteChangedService>();

MainLayout.razor

Then in the layout:

<select onchange="@SiteIdChanged">
    <option value="1">Site 1</option>
    <option value="2">Site 2</option>
</select>

@code{
    [Inject] private NotifiySiteChangedService? service { get; set; }
    private NotifiySiteChangedService Service => service!;

    public int SiteId { get; set; }

    void SiteIdChanged(ChangeEventArgs e)
    {
        if (e.Value != null)
        {
            SiteId = int.Parse(e.Value.ToString());
            Service.OnSiteChanged(this, new SiteIdChangeEventArgs(SiteId));
        }
    }
}

Index.razor

@code {
    [Inject] private NotifiySiteChangedService? service { get; set; }
    private NotifiySiteChangedService Service => service!;

    public int SiteId{get;set;}
    void SiteIdChanged(object? sender, EventArgs e)
    {
        SiteId = ((SiteIdChangeEventArgs)e).SiteId;
    } 

    protected override void OnInitialized()
    {
        this.Service.SiteChanged += this.SiteIdChanged;
        base.OnInitialized();
    }
}

Upvotes: 2

Related Questions