So the thing is I have a little sandbox to play with Blazor. There is a basic form with a few fields. I'm trying to put some validation on that. The input fields are custom component, applied some bootstrap on them. In short, this is the input component:
@using System.Linq.Expressions
<div class="input-group mb-3">
<span class="input-group-text" id=@Id>@Label</span>
<InputText @bind-Value=@Value @oninput=OnInput type="text" class="form-control" placeholder=@PlaceHolder aria-label=@Label aria-describedby=@Id />
<ValidationMessage For=@For />
</div>
@code {
[Parameter]
public string Id { get; set; }
[Parameter]
public string Label { get; set; }
[Parameter]
public string PlaceHolder { get; set; }
[Parameter]
public string Value
{
get => _value;
set
{
if (_value != value)
{
_value = value;
ValueChanged.InvokeAsync(value);
}
}
}
private string _value;
[Parameter]
public EventCallback<string> ValueChanged { get; set; }
[Parameter]
public Expression<Func<string>> For { get; set; }
[Parameter]
public Func<string> OnFormChange { get; set; }
private async Task OnInput(ChangeEventArgs e)
{
Value = e?.Value.ToString();
await ValueChanged.InvokeAsync(Value);
}
}
and a piece from the page:
...
<div class="container-sm">
<Web.Components.Modal Id="exampleModal" Title="Fegyver bevezetése" OnSave="HandleSave" TriggerValidation="Validate" IsValid=@ModalIsValid>
<EditForm Model=@weaponUnderEdit OnValidSubmit="HandleValidSubmit" OnInvalidSubmit="HandleInvalidSubmit">
<DataAnnotationsValidator />
...
@* <Web.Components.TextInput Id="weight" Label="Súly" PlaceHolder="Súly pl.: 0.3 (Tőr), 2.5 (Csatacsákány)" @[email protected] For="@(() => @weaponUnderEdit.Weight)" /> *@
<Web.Components.TextInput Id="price" Label="Ár" PlaceHolder="Ár pl.: 1a 2e 3r, 1e 50r" @[email protected] For="@(() => @weaponUnderEdit.Price)" />
<ValidationSummary />
</EditForm>
</Web.Components.Modal>
</div>
...
of course, there are data annotation attributes on the model:
public class CommonWeaponPrototype
{
...
[Required, RegularExpression(@"^\d+(\.\d{1,2})?$")]
public string Weight { get; set; }
[Required, RegularExpression(@"^\d+(\.\d{1,2})?$")]
public string Price { get; set; }
}
Now the validation works like that:
Everything there... and if the second input is uncomment... everything gone; no more validation.
So far tried to use custom validation, maybe I can do with that, using Regex check and so on... but it is really annoying that I can't make this work, and also, why custom? It is a really simple form to validate, some regex will it be.
I've simplified your code a little to demonstrate a working model.
First, your custom component. Mine inherits from InputText
, which uses all the built in functionality and just changes the input
formatting. It implements correct binding.
@using System.Linq.Expressions
@inherits InputText
<div class="input-group mb-3">
<span class="input-group-text">@Label</span>
<input @bind:get="@Value" @bind:set="OnValueChanged" @bind:event="oninput" type="text" class="form-control" placeholder=@PlaceHolder />
<ValidationMessage For="ValueExpression" />
</div>
@code {
[Parameter] public string? Label { get; set; }
[Parameter] public string? PlaceHolder { get; set; }
private Task OnValueChanged(string? value)
{
CurrentValueAsString = value;
return Task.CompletedTask;
}
}
And then the demo page:
@page "/"
@using System.ComponentModel.DataAnnotations
<PageTitle>Home</PageTitle>
<EditForm EditContext="_editContext" OnValidSubmit="this.OnValidSubmit">
<DataAnnotationsValidator />
<MyInput @bind-Value="_model.Weight" Label="Weight" />
<MyInput @bind-Value="_model.Price" Label="Price" />
</EditForm>
@code {
private Model _model = new();
private EditContext? _editContext;
protected override void OnInitialized()
{
_editContext = new(_model);
}
public Task OnValidSubmit()
{
// Do something
return Task.CompletedTask;
}
public class Model
{
[Required, RegularExpression(@"^\d+(\.\d{1,2})?$")]
public string? Weight { get; set; }
[Required, RegularExpression(@"^\d+(\.\d{1,2})?$")]
public string? Price { get; set; }
}
}