2
votes

I am just getting up to speed on Server side Blazor (not webassembly), so forgive me if this is a silly question.

What I am trying to do is have service which can be used to display a toast. The component Library I am using is from Syncfusion. I can use this just fine in the usual way where it is embedded on each component where it is needed.

<SfToast ID="toast_default" @ref="Toaster" CssClass="e-toast-success" content="@ViewModel.ToastMessage" Timeout="2000" Icon="e-meeting">
     <ToastPosition X="Right" ></ToastPosition>
</SfToast>

I can use this in the code behind and it displays a toast as expected.

But I have many pages that use this code and would like to not repeat myself. I would like to be able to use the above once in app.razor, and then get a reference to it, and then it throughout the app. For example, in the onIntializedAsync, I get a reference to the Toaster, save it to an injected service. Then I use the same service throughout the app.

I coded the above, but Toaster is always null in the service.

    public class MessageService
    {
        public SfToast Toaster { get; set; }

        public async Task SendMessage(string message)
        {
            if(this.Toaster!= null)
            {
                await this.Toaster.Show(new ToastModel() { Content = message });
            }
        }
    }

This is the code in App.razor. I have stepped through the code and it sets the reference to Toaster correctly, but when the message service tries to get it to use it, it is null.

@code {

    public SfToast Toaster { get; set; }

    protected override Task OnInitializedAsync()
    {
        this.MessageService.Toaster = this.Toaster;
        return base.OnInitializedAsync();
    }
}

Is there another way to do this? Or am I making some mistake?

2
I inject a scoped service. This service has ShowMessage method. My SfToast is only on main layout. Main layout sets a delegate to scoped service, this delegate is able to show messages through toast. When you say to scoped service to show a message, it uses this delegate.dani herrera
the easiest way is to use a CascadeParameternAviD
@nAviD, Thank you, I think you are right. If you want to post as an answer, I will accept.Greg Gum
@daniherrera, I am not sure what you mean by "Main layout sets a delegate". Can you explain more?Greg Gum

2 Answers

1
votes

The easiest way is to use a CascadeParameter.

1
votes

Based on @nAviD's answer, I did this:

MainLayout.razor sets up the cascading parameter. The toaster components sets a @ref in the MessageService.

@inherits LayoutComponentBase
@using JusticeOnTheWeb.Core

<CascadingValue Value="MessageService">
    <div class="content">
        @Body
    </div>
</CascadingValue>

<SfToast ID="toast_default" @ref="MessageService.Toaster" CssClass="e-toast-success" Timeout="2000" Icon="e-meeting">
    <ToastPosition X="Right"></ToastPosition>
</SfToast>

@code{

    public MessageService MessageService { get; set; } = new MessageService();

}

Then it gets consumed by MyComponent.razor:

<SfButton @onclick="ShowMessage">Show Message</SfButton>


@code {

    [CascadingParameter]
    public MessageService MessageService { get; set; }

    public void ShowMessage()
    {
        this.MessageService.Show("42");
    }
}