Blazor one toast control on MainLayout

Hello,

is it possible to have one toast control on the MainLayout razor page and access this from all child pages?

I want to prevent to put the same logic and controls on each page. I've been trying with the @ref attribute and injecting an AppState, but I cannot get it working.



21 Replies

IS Indrajith Srinivasan Syncfusion Team April 9, 2020 12:35 PM UTC

Hi Davy,

Greetings from Syncfusion support,

We have validated your reported query. Yes, you can render the toast in the MainLayout page and can access it from other pages. We have also prepared a sample based on your requirements.

Sample: https://www.syncfusion.com/downloads/support/forum/153145/ze/Toast_reusable-1920152305

Can you please try out the above solution and let us know if it meets your requirements?

Regards,
 
Indrajith 



DA Davy April 9, 2020 02:18 PM UTC

Thank you for your quick reply. I can see the sample is working as expected, however this is Blazor server side and I am trying to do it with Blazor client side. 

It seems in this case I cannot use the <MainLayout> component on a child page, because it would render everything twice.

It would be great if you could provide me with a sample on how to accomplish this client side.


IS Indrajith Srinivasan Syncfusion Team April 10, 2020 08:18 AM UTC

Hi Davy,

Thanks for the update,

Yes, we have prepared a sample based on your requirements with the client app. Can you please check the below sample.

Sample: https://www.syncfusion.com/downloads/support/forum/153145/ze/Toast_reusable_client-410191894

Please let us know if you need any further assistance with this?

Regards,
 
Indrajith 



DA Davy April 10, 2020 08:43 AM UTC

Ok, thanks again for this sample. I can see now what I was missing yesterday.

However your proposed solution looks a bit like a bad workaround, not a real solution you want to use in a production environment. The page renders the master layout twice and you hide the double rendered div's with css, display: none.


This is not an acceptable solution!

A better solution would be to have some kind of NotificationService of NotificationManager which can be registered as scoped and then can be injected and used throughout the entire application.

I'll be happy to hear if you can propose another solution to my question.


DA Davy April 10, 2020 01:14 PM UTC

Another issue I have with the SfToast component, is that it is not working together with the SfSidebar component.

As soon as you have both components on one page, the toasts are not shown anymore. They are added to the HTML of the page, but they stay hidden with the css class "e-blazor-toast-hidden".

I've added a sample of this issue.

Attachment: Toast_reusable_client4101918942_2e4f033b.zip


IS Indrajith Srinivasan Syncfusion Team April 13, 2020 02:55 PM UTC

Hi Davy,

Thanks for the update,

We have validated your reported queries and below are the responses for it.

Query 1: “The page renders the master layout twice and you hide the double rendered div's with css, display: none.“

The page is rendered twice because the layout page name <MainLayout> is used in the default page rendering on using this, the page is rendered twice hence suggested solution for hiding them. In order to resolve this, you can assign toast to a separate razor file and call from the child pages. We have also modified the sample you have shared.

Sample: https://www.syncfusion.com/downloads/support/forum/153145/ze/BLAZOR~1-926542281
 

Query 2: “Another issue I have with the SfToast component, is that it is not working together with the SfSidebar component.“
 
 
We have faced Toast rendering issues with the 18.1.42 version in the web assembly applications, hence you have faced such issues. Upgrading to the latest version 18.1.43 that will resolve the reported issue with toast.

Please let us know if the solution helps,

Regards,
 
Indrajith 



UN Unknown April 13, 2020 06:35 PM UTC

Hi Davy,

i solved it this way:

I have on the mainlayout a toast. The toast passes itself as cascading value to every child component. On the child components i access it as a cascading parameter. Works fine for us and i think that's the blazor approach to solve it.. 
Any reason not to do it that way?

Nils


DA Davy April 14, 2020 02:46 PM UTC

Thank you both. 

@Indrajith: I can confirm that the toast is working after upgrading to the latest version.

@Nils: I didn't know about cascading values yet, but I've looked into it today and it seems to be working fine. I still believe that having some kind of NotificationService of NotificationManager which can be registered as scoped and then can be injected, is a better and cleaner solution. But I guess your way is the way I'll be using it for now. Thanks!


IS Indrajith Srinivasan Syncfusion Team April 15, 2020 08:01 AM UTC

Hi Davy,

Welcome,

Please let us know if you need any further assitance.

Regards, 
Indrajith 



JM Jeff Michelson October 7, 2020 06:43 AM UTC

Here's my solution:  https://github.com/Blazored/Toast


SR Sabitha Rajamani Syncfusion Team October 8, 2020 07:15 AM UTC

Hi Jeff, 
 
Thanks for the update. 
 
Regards, 
Sabitha 



AL Alex replied to Davy November 19, 2021 01:05 AM UTC

Looking at this forum a year later.

I believe having a service that can be injected to do this would be a great addition to syncfusion.

Looking at other blazor components, for example Radzen, they provide such a service and it works really well.



IS Indrajith Srinivasan Syncfusion Team November 19, 2021 10:56 AM UTC

Hi Alex, 
 
Greetings from Syncfusion support, 
 
We have validated on the reported query. You can also render the SfToast as an service in the Blazor. By creating reusable SfToast, which can be invoked anywhere from the server that tries to your requirements.   
   
Follow below steps to configure the SfToast as an service, 
  1. Create folder Components in the root folder
  2. Add ToastOption.cs class file and add below codes (If require more SfToast properties, add and configure in ToastComponent)
   
   
using Microsoft.AspNetCore.Components;  
  
namespace BlazorSignalRApp.Components  
{  
    public class ToastOptions  
    {  
        public string Title { getset; }  
        public string Content { getset; }  
    }  
}  
   
   
  1. Add ToastService.cs class file and add below codes
   
   
using System;  
using Microsoft.AspNetCore.Components;  
  
namespace BlazorSignalRApp.Components  
{  
    public class ToastService  
    {  
        public event Action<ToastOptions> ToastInstance;  
  
        public void Open(ToastOptions options)  
        {  
            // Invoke ToastComponent to update and show the toast with messages  
            this.ToastInstance.Invoke(options);  
        }  
    }  
}  
   
   
  1. Add ToastComponent.razor file and add below codes
   
   
@using Syncfusion.Blazor.Popups;  
@using Syncfusion.Blazor.Notifications;  
  
  
<SfToast @ref="ToastObj" Timeout=3000>  
    <ToastTemplates>  
        <Title>  
            @Options.Title  
        </Title>  
        <Content>  
            @Options.Content  
        </Content>  
    </ToastTemplates>  
    <ToastPosition X="Right"></ToastPosition>  
</SfToast>  
  
@code {  
    [Inject]  
    public ToastService ToastService { getset; }  
    SfToast ToastObj;  
  
    private bool RenderToast { getset; } = false;  
  
    // Parameter  
    private ToastOptions Options = new ToastOptions();  
  
    protected override async Task OnInitializedAsync()  
    {  
        // Update the parameter in local variable and render the toast  
        ToastService.ToastInstance += (ToastOptions options) =>  
        {  
            InvokeAsync(() =>  
            {  
                this.Options.Title = options.Title;  
                this.Options.Content = options.Content;  
                this.RenderToast = true;                  
                this.StateHasChanged();  
                this.ToastObj.ShowAsync(); 
            });  
        };  
    }  
}  
   
   
  1. Register the ToastService in the Startup.cs file as like below
   
   
using BlazorSignalRApp.Components;  
   
namespace BlazorSignalRApp  
{   
    public class Startup   
    {   
        public void ConfigureServices(IServiceCollection services)  
     {  
            ...       
        services.AddScoped<ToastService>();             
            ...   
        }   
    }   
}   
   
   
                            
   
  1. Initialize the ToastComponent, end of the MainLayout.razor file for update the instance in ToastService
   
   
@using BlazorSignalRApp.Components  
   
   
   
  
<ToastComponent />  
   
   
  1. Update the SfToast dynamically in the options, which will load a content to SfToast
  2. Add below code in Index.razor file and run the application
   
                                        
@page "/"   
   
@using BlazorSignalRApp.Components  
  
@inject ToastService ToastServices  
  
<button class="e-btn" @onclick="@ShowToast1"> Show Toast</button>  
  
@code {  
    private void ShowToast1()  
    {  
        this.ToastServices.Open(new ToastOptions()  
        {  
            Title = "Toast Title",  
            Content = "Toast content"// Dynamic Content  
        });  
    }  
}  
   
 
 
Please let us know if the solution helps, 
 
Regards, 
Indrajith  



TA Tarik Alkathiri December 4, 2021 01:10 PM UTC

Thank you very much for the above sample.

I have downloaded the sample, every thing works fine, but when I make the CssClass as one the service options it dos not show the style as expected how ever when I click the second time to show the toast it applies the style and every things in ToastOptions show as expected but after the second click.

Thank you very much for your support. 



VJ Vinitha Jeyakumar Syncfusion Team December 7, 2021 02:18 PM UTC

Hi Tarik, 
 
 
We have validated your query “when I make the CssClass as one the service options it does not show the style as expected 
 
We can able to reproduce the reported issue at our end and the issue occurs since the CssClass property was bound later in Toast. You can resolve the reported issue, by setting the minimal delay to the property changes to take place properly. Please check the code below, 
 
Code snippet: 
Index.razor 
@using BlazorSignalRApp.Components 
 
@inject ToastService ToastServices 
 
<button class="e-btn" @onclick="@ShowToast1"> Show Toast</button> 
 
@code { 
    private async Task ShowToast1() 
    { 
        await Task.Delay(1); 
        this.ToastServices.Open(new ToastOptions() 
        { 
            Title = "Toast Title", 
            Content = "Toast content", // Dynamic Content 
            CssClass = "glow" 
        }); 
    } 
} 
 
 
Please check the sample and code snippet and let us know if it resolves your reported issue. 
 
Regards, 
Vinitha 



JV Jay Vansjalia March 8, 2022 06:09 PM UTC

Hi Vinitha,


I have download the provided solution for global toast message. Unfortunately, it does not work for me. Currently I am using .NET 6 with Blazor Server App. Can you please provide a updated version for .NET 6?


Any help would be highly appreciated.


Thanks & Regards,

Jay



BS Buvana Sathasivam Syncfusion Team March 9, 2022 06:07 PM UTC

Hi Jay, 

Thank you for your update. 

We have prepared a sample based on the Toast service using .Net 6 with the Blazor Server App. Could you please find the below sample? 


Please let us know if you have any other concerns. 

Regards, 
Buvana S 



MA Marco April 18, 2022 10:12 PM UTC

Hi everyone,


I was trying to find a solution for this same issue and came across this forum.

I took a look at the solutions proposed (in special the latest one - Buvana's .Net 6 Toast Service), however I found out a solution which, IMHO, looks simpler (please not I'm rather new at Blazor).


Basically I created a component with a CascadingValue called AppToast:

<CascadingValue Value="this">

    @ChildContent


    <SfToast @ref="_toast" ShowProgressBar="true" ShowCloseButton="true" Width="350px"
             Title="@_title" Content="@_contents" Timeout="@Timeout" CssClass="@_cssClass" Icon="@($"fa {_icon}")">
        <ToastPosition X="Center" Y="Top" />
        <ToastAnimationSettings>
            <ToastShowAnimationSettings Effect="ToastEffect.SlideTopIn"></ToastShowAnimationSettings>
            <ToastHideAnimationSettings Effect="ToastEffect.FadeOut"></ToastHideAnimationSettings>
        </ToastAnimationSettings>
    </SfToast>
</CascadingValue>


@code {
    [Parameter]
    public RenderFragment ChildContent { get; set; } = default!;


    [Parameter]
    public int Timeout { get; set; } = 5000;


    private SfToast _toast = default!;


    private string _title = default!;
    private string _contents = default!;
    private string _cssClass = default!;
    private string _icon = default!;


    public async Task ShowSuccessAsync(string message)
    {
        _title = "Success";
        _cssClass = "e-toast-success";
        _icon = "fa-circle-check";
        await ShowAsync(message);
    }


    public async Task ShowInfoAsync(string message)
    {
        ...
    }


    public async Task ShowWarningAsync(string message)
    {
        ...
    }


    public async Task ShowErrorAsync(string message)
    {
        ...
    }


    private async Task ShowAsync(string message)
    {
        _contents = message;
        StateHasChanged();
        await _toast.ShowAsync();
    }
}




Then I just wrapped this component around my MainLayout Component:

<AppToast>

<div class="page">
...


<main class="main-content">
<article class="content px-4">
@Body
</article>
</main>
</div>
</AppToast>


With this setup, in each (Child) component I wish to invoke it, I simply capture the CascadingParameter and invoke the desired method (ShowSuccess, Warning, etc.):

[CascadingParameter]

private AppToast Toast { get; set; } = default!;


...


await Toast.ShowSuccessAsync("The operation succeeded.");


So far, this approach is working well for me.


Best regards,

Marco.



BS Buvana Sathasivam Syncfusion Team April 19, 2022 07:43 AM UTC

Hi Macro,


Thank you for sharing your alternate solution with us. Please let us know if you have any further assistance.


Regards,

Buvana S



DA Davy replied to Indrajith Srinivasan June 1, 2022 10:05 AM UTC

Please note that your toast component is broken in the most recent releases: 

20.1.0.57 and 20.1.0.58


It is impossible to trigger the toast when used as a cascade value or in the sample project you provided here:

Sample: https://www.syncfusion.com/downloads/support/forum/153145/ze/SfToast_as_Service-292090813 





BS Buvana Sathasivam Syncfusion Team June 2, 2022 01:35 PM UTC

Hi Davy,


We have added breaking changes to the 20.1.47 version to add the script and style references. By default, IgnoreScriptIsolation property is enabled. In the below sample, we have enabled IgnoreScriptIsolation.


Startup.cs

services.AddSyncfusionBlazor();


So, you need to manually refer to the script and styles file like below.

Note: You need to install Syncfusion.Blazor.Themes nuget package for referring styles.

_Host.cshtml

<link rel='nofollow' href="_content/Syncfusion.Blazor.Themes/bootstrap5.css" rel="stylesheet" />

     <script src="_content/Syncfusion.Blazor.Core/scripts/syncfusion-blazor.min.js" type="text/javascript"></script>


Documentationhttps://blazor.syncfusion.com/documentation/common/adding-script-references


Release Noteshttps://blazor.syncfusion.com/documentation/release-notes/20.1.47?type=all#breaking-changes


We have upgraded the sample to the 20.1.0.58 version with the above breaking changes. Can you please find the below sample?

Samplehttps://www.syncfusion.com/downloads/support/directtrac/general/ze/SFB7C0~1-577141057


Please let us know if you have any concerns.


Regards,

Buvana S


Loader.
Up arrow icon