Open Closed

Extending razor components - Blazor #1148


0
Leonardo.Willrich created

ABP Framework version: v4.2.3 rc.1 UI type: Blazor DB provider: EF Core Tiered (MVC) or Identity Server Separated (Angular): yes / no Exception message and stack trace: Steps to reproduce the issue:

Hi,

If I have to extend the component DefaultLayout from Volo.Abp.AspNetCore.Components.Web.LeptonTheme.Components.ApplicationLayout, do I need to rewrite the whole markups elements or it will be inherited?

I was not able to inherited the elements, I had to rewrite them again. I don't want to do that because I just want to override the method OnInitialize().

My new components:

@using Volo.Abp.AspNetCore.Components.Web.LeptonTheme.Components.ApplicationLayout
@inherits DefaultLayout
@using Volo.Abp.Ui.Branding
@using Volo.Abp.BlazoriseUI.Components
@using Volo.Abp.AspNetCore.Components.Web.LeptonTheme.Components.ApplicationLayout.MainHeader
@using Volo.Abp.AspNetCore.Components.Web.LeptonTheme.Components.ApplicationLayout.MainFooter
@inject IBrandingProvider BrandingProvider
<MainHeader />
<div class="lp-content h-100">
    <PageAlert />
    @Body
    <UiMessageAlert />
    <UiNotificationAlert />
</div>
<MainFooterComponent />

That is the code that I don't want to have to rewrite. I would like that would be inherited from DefaultLayout as specified by @inherited DefaultLayout

Code-behind:

using Microsoft.AspNetCore.Components;
using System;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Components.Web.LeptonTheme.Components.ApplicationLayout;
using Volo.Abp.DependencyInjection;

namespace TVD_Holdings_Ltd.AvalancheOCP.Blazor.Components.ApplicationLayout
{
    [ExposeServices(typeof(DefaultLayout))]
    [Dependency(ReplaceServices = true)]
    public partial class DefaultLayoutExtension 
    {

        [Inject] IConfiguration Configuration { get; set; }
        [Inject] IAlertManager _alertManager { get; set; }
        private HubConnection hubConnection;

        protected override async Task OnInitializedAsync()
        {
            // Do something
        }
    }
}


4 Answer(s)
  • 0
    mladen.macanovic created
    Support Team

    This is how Blazor works.

    You cannot inherit razor code part. You can only inherit from the class type. What I mean my that? Well, you must know what razor file represents in Blazor component. Basically, it is a RenderFragment that is rendering (in pseudo code).

    override void Render()
    {
       // render elements
    }
    

    Once compiled it is just a regular Render method. That is why you can't inherit it. You must write the implementation again.

    Regerding you problem with OnInitializedAsync, I think you can do that. Instead of inherting both .razor and .cs, inherit only the class part.

    using Microsoft.AspNetCore.Components;
    using System;
    using System.Threading.Tasks;
    using Volo.Abp.AspNetCore.Components.Web.LeptonTheme.Components.ApplicationLayout;
    using Volo.Abp.DependencyInjection;
    
    namespace TVD_Holdings_Ltd.AvalancheOCP.Blazor.Components.ApplicationLayout
    {
        [ExposeServices(typeof(DefaultLayout))]
        [Dependency(ReplaceServices = true)]
        public class DefaultLayoutExtension : DefaultLayout
        {
    
            [Inject] IConfiguration Configuration { get; set; }
            [Inject] IAlertManager _alertManager { get; set; }
            private HubConnection hubConnection;
    
            protected override async Task OnInitializedAsync()
            {
                // Do something
            }
        }
    }
    
  • 0
    Leonardo.Willrich created

    Hi mladen.macanovic,

    Thank you for your answer. I got your point and I am rewriting the razor part as well.

    I've tried your suggestion with MainHeader component, only inheriting the class part, but that doesn't work, see below:

    Code:

    using System;
    using System.Threading.Tasks;
    using Volo.Abp.AspNetCore.Components.Web.LeptonTheme.Components.ApplicationLayout.MainHeader;
    using Volo.Abp.DependencyInjection;
    
    namespace TVD_Holdings_Ltd.AvalancheOCP.Blazor.Components.Layout
    {
        [ExposeServices(typeof(MainHeader))]
        [Dependency(ReplaceServices = true)]
        public class MainHeaderExtension : MainHeader
        {
            protected override async Task OnInitializedAsync()
            {
                Console.WriteLine("MainHeader Init");
            }
        }
    }
    

    Error:

    My only concern overriding the .razor and .razor.cs is updating the framework and getting conflit or missing some changes due to overriden files.

  • 0
    mladen.macanovic created
    Support Team

    I tried the same logic in Blazorise code and it working fine. Might be something in ABP that is interfering maybe. I will need to investigate more and get back to you.

    In the meantime just use both .razor and .razor.cs. While not the pretiest, it is a working solution.

  • 0
    Leonardo.Willrich created

    Hi mladen,

    Please, don't prioritize that! I have a workaround and I end up adding one more component to the layout anyway to show a modal message. I'll close this thread, I appreciate your help and explanation.