#c# #html #blazor #blazor-webassembly
Вопрос:
При использовании blazor важно создавать многоразовые пользовательские компоненты; это один из основных моментов использования Blazor.
Я создал базовый компонент ввода, который использует Bootstrap для своего CSS, как показано на рисунке.
@inherits InputBase<string>
<InputText type="@Type"
class="form-control"
id="@_id"
placeholder="@Placeholder"
@bind-Value="CurrentValue"
disabled="@Disabled"
@attributes="AdditionalAttributes"/>
/* Additional properties below for placeholder, disabled, type, etc. they're just string properties */
Я помещаю это в форму редактирования, вот так…
<EditForm Model="MyModel"
OnValidSubmit="ViewModel.CreateAsync">
<DataAnnotationsValidator />
<PrimaryInput @bind-Value="MyModel.Name"
Placeholder="Name..."/>
</EditForm>
Проблема в том, что это не добавляет «недопустимый» класс к элементу. Отображаются как допустимые, так и измененные, но как только ввод становится недействительным, он не меняется на недопустимый, как это было бы с настраиваемым компонентом none. Это моя модель ниже, чтобы показать, что я добавил проверку в модель.
public class MyModel
{
[StringLength(5)]
[Required]
public string Name { get; set; }
}
Ниже приведено изображение того, что отображается:
Это html-код, который генерируется Blazor…
<input type="text" id="aa106d17-46d7-442c-be39-6c947f17186b" placeholder="Name..." aria-describedby="14b1189e-c3c5-4e1f-ae1d-330756147b44" class="form-control valid" aria-invalid="">
…как вы можете видеть, класс все еще действителен, но был применен недопустимый атрибут aria. Ниже приведен HTML — код для проверки ввода пользовательского компонента none…
<input class="modified invalid" aria-invalid="">
…в этом случае применяется недопустимое значение. Что-то мешает классу переключиться на недопустимый в пользовательском компоненте.
Ответ №1:
Вам нужно запустить форму EditContext
. Есть несколько способов сделать это — я опишу два из них.
Внутри вашего пользовательского компонента вы можете переопределить TryParseValueFromString
и обработать там проверку — InputBase<>
в нем есть эти свойства. Это может не иметь смысла, учитывая, что ваш тип string
уже является а.
В противном случае вы можете сделать так, чтобы ваш пользовательский компонент содержал EditContext
инъекцию в качестве каскадного параметра, а затем выполнить обратный вызов события при изменении, чтобы вызвать EditContext
«ы NotifiedFieldChanged
«.
Небольшой пример ниже этого второго примера:
[CascadingParameter]
private EditContext EditContext { get; set; }
[Parameter]
private Expression<Func<string>> ValueExpression { get; set; }
private FieldIdentifier _field;
private void OnInitialized()
{
_field = FieldIdentifier.Create(ValueExpression);
}
private void OnInputChanged(ChangeEventArgs args)
{
EditContext.NotifyFieldChanged(_fieldIdentifier);
}
Комментарии:
1. Не могли бы вы рассказать немного подробнее? Не совсем уверен, что я делаю, или есть какая-то документация, где это описано? Я пробую ваш второй пример и не совсем уверен, что мне делать.
<input @bind-value="@Value" class="form-control" @onchange="OnInputChanged" />
Вот мой код, тогда у меня также есть пример кода, который вы опубликовали в своем ответе, но я не уверен, как все это должно выглядеть.
Ответ №2:
Я исправил это с помощью следующего кода в моем пользовательском компоненте….
@inherits InputText
<InputText class="form-control"
Value="@Value"
ValueExpression="ValueExpression"
ValueChanged="OnInputChanged" />
… немного странно наследовать входной текст с входным текстом внутри. Мой код, стоящий за этим, таков…
private void OnInputChanged(string value)
{
CurrentValueAsString = value;
EditContext.NotifyFieldChanged(FieldIdentifier);
}
Затем в своем коде я помещаю этот компонент вот так….
<TestInput @bind-Value="ViewModel.Menu.Name"/>
Это немного странная работа, но она выполняет свою работу и применяет правильные классы, когда она действительна/недействительна.
Ответ №3:
Вы наследуете от <InputBase>
и помещаете InputText
( InputBase
элемент управления) внутри него. Это действительно не имеет смысла.
Вот пример, демонстрирующий, как настроить стандарт InputText
. В нем показано, как добавлять пользовательские атрибуты , один из способов обработки disabled
, как введенные пользователем атрибуты добавляются к входным данным, и это обновляет значение при вводе с клавиатуры, а не при потере фокуса.
@namespace Blazor.Starter.Components
@inherits InputText
<input type="text" disabled="@Disabled" value="@this.CurrentValue" @oninput="OnInput" @ref="Element" id="@Id" @attributes="this.AdditionalAttributes" />
@code{
[Parameter] public ElementReference? Element { get; set; }
[Parameter] public string? Id { get; set; }
[Parameter] public bool Disabled { get; set; }
private void OnInput(ChangeEventArgs e)
=> this.CurrentValueAsString = e.Value.ToString();
}
@page "/Test3"
<EditForm EditContext="@_editContext" OnValidSubmit="@HandleValidSubmit">
<DataAnnotationsValidator />
<ValidationSummary />
<label class="form-label">First Name</label>
<CustomInput class="form-control" @bind-Value="this._formModel.FirstName" Id="mycontrol"></CustomInput>
<label class="form-label">First Name</label>
<CustomInput class="form-control" @bind-Value="this._formModel.FirstName" Id="mydisabledcontrol" Disabled="true"></CustomInput>
<div class=" m-2 p-2">
<button type="submit" class="btn btn-primary">New Person</button>
</div>
<div class="p3-m-3">Value: @_formModel.FirstName</div>
</EditForm>
@code {
private EditContext? _editContext;
private FormModel _formModel;
private void HandleValidSubmit()
{
// handler
}
private class FormModel
{
[StringLength(5)][Required] public string FirstName { get; set; }
}
protected override Task OnInitializedAsync()
{
_formModel = new FormModel();
_editContext = new EditContext(_formModel);
return base.OnInitializedAsync();
}
}
Ария Меняется
Смотрите два фрагмента html, чтобы узнать, когда ввод является допустимым/недопустимым.
<input type="text" id="mycontrol" class="form-control" _bl_759b54c2-54a4-461f-8101-9661c9034c17>
<input type="text" id="mycontrol" class="form-control" _bl_759b54c2-54a4-461f-8101-9661c9034c17 aria-invalid>
Комментарии:
1. Я ценю время, которое вы потратили на свой ответ, но это не решает проблему, с которой я сталкиваюсь, когда класс «недопустимый» не добавляется, даже если входное значение неверно.
2. Если вы настроите и запустите мой пример, вы увидите
aria-invalid
, как он появляется и исчезает какfirstname
есть/недействителен.3.
aria-invalid
добавляется к моему тоже независимо от того, является ли он действительным или недействительным, в своем вопросе я говорю, как класс не меняется, чтобы отразить недопустимое/допустимое состояние ввода, и это то, что мне нужно. Чтобы я мог применять стили, основанные на допустимом/недопустимом состоянии входных данных.4.
InputBase
добавляет/удаляет «aria-недопустимый» в/изAdditionalAttributes
свойства на основе состояния проверки элемента управления. В моем коде выше он делает это правильно, добавляя его только в том случае, если поле пустое или содержит более 5 символов. Вы хотите сказать, что хотите применить пользовательский стиль на основе состояния проверки элемента управления?5. Да, в стандартном вводном тексте, как показано в моем коде выше, класс
valid
илиinvalid
применяется на основе проверки модели. Blazor имеет CSS-стиль для этого по умолчанию в файле app.css. Мой вопрос заключается в том, почему недопустимые и допустимые классы не изменяются должным образом в зависимости от состояния проверки в моем пользовательском компоненте.