DavidWaldo
DavidWaldo

Reputation: 735

Wraping button inside custom component and propagating onclick event

I would like to wrap input(type button) inside custom component so that I could apply isolated css and some speciel parameters to control. But how do I propagate onclick and other events from input to my component?

Whhen you use input button you can use onclick event and its settings like this:

<input type="button" @onclick:preventDefault="true" @onclick:stopPropagation="true" @onclick="@someMethod" />

How do I achieve the same with my component? So I can have:

<customBUtton @onclick:preventDefault="true" @onclick:stopPropagation="true" @onclick="@someMethod" />

thanks for any help

Upvotes: 0

Views: 1298

Answers (3)

Weng Kin
Weng Kin

Reputation: 11

Following allows your button to be generic(does whatever method you linked them in the parent) without calling StateHasChanged() in every method link to a new instance of your component. Please take note that if you mouse over the @onclick attribute, you'll see it is actually "descdending" from EventCallBack and you should do the same to your Button component. Otherwise, the method will only happen within the component without the knowledge of the parent. Remarks: Calling StateHasChanged() in your Button component wouldn't update the view.

CustomButton.razor

<button class="someCssClasses" @onclick="InvokeAction" @onclick:preventDefault="ShouldPreventDefault">@Text</button>

@code{

    [Parameter]
    public EventCallBack<Action> Action {get ;set;}

    [Parameter]
    public string Text{get ;set;}

    [Parameter]
    publick bool ShouldPreventDefault {get; set;}

    private void InvokeAction()
    {
        Action.InvokeAsync();
    }
}

and how you consume it:

<CustomButton Text="Add" Action="IncrementCount" ShouldPreventDefault="True" />
<CustomButton Text="Add" Action="DecrementCount" ShouldPreventDefault="True" />

Upvotes: 0

M. Folmer
M. Folmer

Reputation: 300

You could use a EventCallback or EventCallback<T>. These are better suited compared to Action or Func as the callback could have to call StateHasChanged in order to render changes. Using EventCallback or EventCallback<T> this call is done by the framework automatically.

Say you have some child component:

<button @onclick="@(() => OnClick.InvokeAsync("eventcallback invoked"))">Click me</button>

@code {
    [Parameter] public EventCallback<string> OnClick { get; set; }
}

Then a parent component

<ChildComponent OnClick="Handler"></ChildComponent>
@code {
    void Handler(string message) 
    {
        ...
    }
}

Upvotes: 2

Umair
Umair

Reputation: 5481

The best option is to create a custom input control by inheriting from InputBase in Blazor. Have a look at this guide: https://chrissainty.com/building-custom-input-components-for-blazor-using-inputbase/

More info here: https://blazor-university.com/forms/descending-from-inputbase/

Here is a sample code using razor page for elements and inheriting from InputBase: https://github.com/chrissainty/BuildingCustomInputComponentsForBlazorUsingInputBase/blob/master/Blazor.App/Shared/CustomInputSelect.razor

Here is some basic code to get started:

public class SwInputTextBase : InputBase<string>
{
    [Parameter] public string Id { get; set; }
    [Parameter] public string Label { get; set; }
    [Parameter] public Expression<Func<string>> ValidationFor { get; set; }

    protected override bool TryParseValueFromString(string value, out string result, out string validationErrorMessage)
    {
        // add more logic here

        result = value;
        validationErrorMessage = null;
        return true;
    }
}

Upvotes: 1

Related Questions