Search code examples
blazorblazor-webassemblyasp.net-blazor

blazor add parameters to templated component


I have a Blazor Popup that takes a template to show his content:

CustomPopup.razor

<Popup
    @bind-Visible="@CreatePopupVisible"
    HorizontalAlignment="HorizontalAlignment.Center"
    VerticalAlignment="VerticalAlignment.Center"
    ShowFooter="true"
    HeaderText="@("Create" + Label)">
    <BodyTemplate>
        @EditForm
    </BodyTemplate>
    <FooterContentTemplate>
    </FooterContentTemplate>
</Popup>

@code {
    [Parameter]
    public string? Label { get; set; }

    [Parameter]
    public RenderFragment EditForm { get; set; }

    bool CreatePopupVisible { get; set; }

}

to this component i pass an EditForm with 2 buttons that takes a function to handle the cancel option:

CustomEditForm.razor

<EditForm Model="Entity" OnValidSubmit="@HandleValidSubmit">
    <DataAnnotationsValidator />
    <ValidationSummary />
    <div class="d-flex flex-column">
        <InputNumber id="factory-id" class="mt-2 mb-2" @bind-Value="Entity.Id" />
        <InputText id="factory-businessname" class="mt-2 mb-2" @bind-Value="Entity.BusinessName" />
        <InputText id="factory-address" class="mt-2 mb-2" @bind-Value="Entity.Address" />
        <div class="d-flex flex-row">
            <button class="btn btn-primary mt-2 mb-2 flex-grow-1" type="submit">Modifica</button>
            <button @onclick="HandleCancel" class="btn btn-secondary mt-2 mb-2 flex-grow-1" type="submit">Annulla</button>
        </div>
    </div>
</EditForm>

@code {

    [Parameter]
    public Action HandleCancel { get; set; }
    

    [Parameter]
    public Factory Entity { get; set; }
    
    private void HandleValidSubmit()
    {
        Logger.LogInformation("HandleValidSubmit called");
    }
}

if i use the EditForm normally like this:

SomeFile.razor

<CustomEditForm HandleCancel="()=>{}">

its all good but when i use it in a templated component how can i pass a function to him from inside the CustomPupup.razor file?

i need to pass a function to set CreatePopupVisible to false when someone clicks on the cancel button

ty in advance for the help!

EDIT

ty for the help but i think i provided not enough information to get the right answer, my bad

so, i want to be able to call the CustomEditForm normally and passing a function defined by the parent to manage the HandleCancel like this:

MainPage.razor

@page ...

<Grid @ref="Grid">
//the grid has a method that closes this CustomEditForm
    <Template>
        <CustomEditForm HandleCancel="() => Grid.CancelRowEdit()"/>
    </Template>
</Grid>

but i also want to close the popup using a function defined inside himself like this:

AnotherPage.razor

<CustomPopup>
    <EditForm>
        <CustomEditForm Entity="new Factory()"/>
    </EditForm>
</CustomPopup>

in this case the edit form should handle the cancel by calling a CustomPopup defined method


Solution

  • It sounds like you just want to pass a reference to an internal method to the RenderFragment, which you can do with RenderFragment<Action> - as HandleCancel expects an Action it can invoke:

    <Popup
        @bind-Visible="@CreatePopupVisible"
        HorizontalAlignment="HorizontalAlignment.Center"
        VerticalAlignment="VerticalAlignment.Center"
        ShowFooter="true"
        HeaderText="@("Create" + Label)">
        <BodyTemplate>
            @EditForm(ClosePopup)
        </BodyTemplate>
        <FooterContentTemplate>
        </FooterContentTemplate>
    </Popup>
    
    @code {
        [Parameter]
        public string? Label { get; set; }
    
        [Parameter]
        public RenderFragment<Action> EditForm { get; set; }
    
        bool CreatePopupVisible { get; set; }
    
        void ClosePopup() 
        {
            CreatePopupVisible = false;
    
            // Because this method will be called by some external code
            // You should tell this component to render:
    
            InvokeAsync(StateHasChanged);
        } 
    }
    

    To use this, the markup can reference the context of the EditForm RenderFragment, which is an Action

    <CustomPopup>
        <EditForm>
            <CustomEditForm Entity="new Factory()" HandleCancel=@context/>
        </EditForm>
    </CustomPopup>
    

    Try it out