Custom Blazor component for InputText

Viewed 108

I want to minify my code by wrapping a large chunk of form code into a seperate component.

What I did was creating MyInput.razor which holds the following code:

<div class="@ColSize">
    <label>@Label</label>
    <InputText @bind-Value="Value" class="form-control" />
    <ValidationMessage For="() => Value" />
</div>

@code {
    public string ColSize { get; set; } = "col-md-12";
    [Parameter] public string Label { get; set; } = string.Empty;
    [Parameter] public string? Value { get; set; }

    [Parameter] public EventCallback<string?> ValueChanged { get; set; }
}

In my Index.razor I've added a simple form with basic validtaion like this:

<EditForm Model="Input" OnValidSubmit="Submit">
    <DataAnnotationsValidator />
    <ValidationSummary />
    <MyInput @bind-Value="Input.Name" />
    
    <button type="submit" class="d-block mt-3">Save</button>
</EditForm>

@code {
    public MyModel Input { get; set; } = new();
    private void Submit()
    {

    }
    public class MyModel
    {
        [MinLength(10)]
        public string Name { get; set; } = string.Empty;
        public string Description { get; set; } = string.Empty;
    }
}

The validation and the binding is working, however, I don't see the validation errors for <ValidationMessage For="() => Value" /> in my component. I can only see the messages with the ValidationSummary.

Is there any easy way to get this working? I don't want to create a new component which inherits from InputText or InputBase. I just want to use the existing input types and wrap some HTML around it so I don't have to type it everytime again.

1 Answers

<ValidationMessage uses and expression to get to the model EditForm is using. You need to pass the expression into your component.

<div class="@ColSize">
    <label>@Label</label>
    <InputText @bind-Value="Value" class="form-control" />
    <ValidationMessage For=@For />
</div>

@code {
    public string ColSize { get; set; } = "col-md-12";
    [Parameter] public string Label { get; set; } = string.Empty;
    [Parameter] public string? Value { get; set; }
    [Parameter] public Expression<Func<TValue>>? For { get; set; } 
    [Parameter] public EventCallback<string?> ValueChanged { get; set; }
}

Usage:

<MyInput @bind-Value="Input.Name" For="() => Input.Name" />

Source code for ValidationMessage

Related