Обратите внимание, что хотя это тесно связано с этим вопросом, ответ там специфичен для одного известного свойства модели, тогда как я хочу, чтобы это работало для любого свойства, поэтому компонент можно использовать повторно.
Я хочу использовать тег Blazor <ValidationMessage>
внутри компонента. Однако, когда я это делаю, сообщение проверки не отображается.
Например, следующий компонент (FormRowText.razor
) создает строку (в смысле сетки Bootstrap), содержащую <input type = "text />
для именованного свойства модели...
<div class = "form-group row">
<label for = "@PropertyName" class = "col-lg-2 col-form-label">@(Caption ?? PropertyName)</label>
<div class = "col-lg-10 input-group">
<div class = "input-group-prepend">
<span class = "input-group-text">
<i class = "far fa-@Icon"></i>
</span>
</div>
<input class = "form-control" Value = "@Value" type = "text"
id = "@PropertyName" name = "@PropertyName" @onchange = "@OnChanged" />
</div>
</div>
@code {
[Parameter]
public string PropertyName { get; set; }
[Parameter]
public string Value { get; set; }
[Parameter]
public EventCallback<string> ValueChanged { get; set; }
[Parameter]
public string Caption { get; set; }
[Parameter]
public string Icon { get; set; }
private async Task OnChanged(ChangeEventArgs cea) =>
await ValueChanged.InvokeAsync(cea.Value?.ToString() ?? "");
}
Используется так...
<EditForm ...>
<FormRowText PropertyName = "@nameof(Customer.Email)" @bind-Value = "_customer.Email" Icon = "at" />
</EditForm>
Если я добавлю <ValidationMessage>
после этой разметки, она будет работать нормально, но если я добавлю ее внутри компонента (именно там, где я хочу, чтобы она была), это не сработает.
Я видел этот ответ от @enet, в котором показано, как это сделать для конкретного известного свойства модели. Однако мой компонент предназначен для работы с любым свойством модели, и я не знаю, как его изменить.
Я попытался добавить параметр для модели (с @typeparam T
вверху файла)...
[Parameter]
public T Model { get; set; }
...и добавив в HTML следующее...
<ValidationMessage For = "() => PropertyName" />
Однако это не работает.
Есть идеи?
Вы можете каскадировать EditContext в свой компонент и использовать его для уведомления об изменении текущего поля.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
public partial class FormRowText
{
[CascadingParameter] EditContext CascadedEditContext { get; set; }
[Parameter]
public string PropertyName { get; set; }
[Parameter]
public string Value { get; set; }
[Parameter]
public EventCallback<string> ValueChanged { get; set; }
[Parameter]
public string Caption { get; set; }
[Parameter]
public string Icon { get; set; }
[Parameter] public Expression<Func<string>> ValueExpression { get; set; }
private async Task OnChanged(ChangeEventArgs cea)
{
await ValueChanged.InvokeAsync(cea.Value?.ToString() ?? "");
var identifier = CascadedEditContext.Field(PropertyName);
CascadedEditContext.NotifyFieldChanged(identifier);
}
}
<div class = "form-group row">
<label for = "@PropertyName" class = "col-lg-2 col-form-label">@(Caption ?? PropertyName)</label>
<div class = "col-lg-10 input-group">
<div class = "input-group-prepend">
<span class = "input-group-text">
<i class = "far fa-@Icon"></i>
</span>
</div>
<input class = "form-control" value = "@Value" type = "text" id = "@PropertyName" name = "@PropertyName"
@onchange = "@OnChanged" />
<ValidationMessage For = "@ValueExpression" />
</div>
</div>
Вам также понадобится
public class Customer
{
[Required]
public string Name { get; set; }
public Country Country { get; set; } = Country.Israel;
[Required]
[DataType(DataType.EmailAddress)]
[EmailAddress]
public string Email { get; set; }
}
@page "/"
@using System.ComponentModel.DataAnnotations;
@using Microsoft.AspNetCore.Components.Forms;
<EditForm EditContext = "EditContext" OnValidSubmit = "HandleValidSubmit">
<DataAnnotationsValidator />
<div class = "form-group">
<label for = "name">Name: </label>
<InputText @bind-Value = "@customer.Name"></InputText>
<ValidationMessage For = "@(() => customer.Name)" />
</div>
<div class = "form-group">
<FormRowDropdownEnum @bind-Value = "customer.Country" Caption = "Country" T = "Country"></FormRowDropdownEnum>
<ValidationMessage For = "@(() => customer.Country)" />
<FormRowText @bind-Value = "customer.Email" Caption = "Email"
PropertyName = "@nameof(Customer.Email)" Icon = "at"></FormRowText>
</div>
<p>
<button type = "submit" class = "btn btn-primary">Save</button>
</p>
</EditForm>
@code{
private Customer customer = new Customer();
private EditContext EditContext;
protected override void OnInitialized()
{
EditContext = new EditContext(customer);
}
public async Task HandleValidSubmit()
{
await Task.Delay(1);
Console.WriteLine("Saving...");
}
}
Поскольку вы используете компонент EditForm, было бы неплохо использовать компоненты Forms, такие как компонент InputText и тому подобное.
В следующем фрагменте кода описывается, как реализовать компонент FormRowText путем создания подклассов компонентов InputText и добавления новых свойств. Обратите внимание, что PropertyName не требуется для работы компонента.
@inherits InputText
<div class = "form-group row">
<label for = "@PropertyName" class = "col-lg-2 col-form-label">@(Caption ?? PropertyName)</label>
<div class = "col-lg-10 input-group">
<div class = "input-group-prepend">
<span class = "input-group-text">
<i class = "far fa-@Icon"></i>
</span>
</div>
<input class = "form-control" @bind = "CurrentValue" type = "text" id = "@PropertyName" name = "@PropertyName" />
<ValidationMessage For = "@ValueExpression" />
</div>
</div>
@code{
[Parameter]
public string Caption { get; set; }
[Parameter]
public string Icon { get; set; }
[Parameter]
public string PropertyName { get; set; }
}
Нет, у меня нет блога. На самом деле я вообще не программист. Я делаю это для удовольствия. Сейчас я работаю волонтером в благотворительной ассоциации, которая раздает горячее питание бедным. В моем профиле есть ссылка для пожертвований ;) По этой ссылке можно перейти ко всем моим ответам, связанным с Blazor: stackoverflow.com/tags/blazor/topusers
Вы не программист? Я зарабатываю этим на жизнь и знаю не так много, как ты! Снимаю шляпу перед вами за вашу צדקה работу. Хорошо, что есть такие люди, как ты. כל הכבוד вам, обязательно подарю!
Спасибо, это именно то, что мне было нужно! У вас есть блог? Если нет - надо! Вы мне очень помогли несколько раз, я хотел бы увидеть больше ваших мыслей и идей.