【问题标题】:How to do validation for a Custom Blazor multiple select component? Error: MultipleSelect requires a value for the 'ValueExpression' parameter如何对自定义 Blazor 多选组件进行验证?错误:MultipleSelect 需要“ValueExpression”参数的值
【发布时间】:2022-06-14 01:55:34
【问题描述】:

我正在创建一个自定义 Blazor 多选组件。在我添加验证之前它一直有效。此外,如果我禁用多选并保持验证打开,它可以工作。

当多选验证开启时,我收到此错误:

InvalidOperationException: MultipleSelect requires a value for the 'ValueExpression' parameter. Normally this is provided automatically when using 'bind-Value'.

我无法使用“绑定值”属性,因为它似乎只适用于“预打包”的 Blazor 组件。

到目前为止,我能够找到的文档仅涉及在不使用多选选项时从 HTML <select> 元素构建自定义组件。

如何在启用多选的情况下对 <select> 元素进行验证?

自定义多选组件

@using CustomComponents.DataModels
@using System.Linq.Expressions
@using System
@using System.Collections.Generic
@inherits InputBase<string>

<div class="row">
    <div class="col-3">
        <select id="@Id" @bind=@CurrentValue class="form-control @CssClass" multiple="multiple" size="@BoxHieght" style="width:@BoxWidth">
            @foreach (var option in Options)
            {
                <option @onclick="@(() => SelectOption(option))" value="@option.Value">@option.Text</option>
            }
        </select>
    </div>
</div>

@code {
    [Parameter]
    public string Id { get; set; }
    [Parameter]
    public List<Option> Options { get; set; } = new List<Option>();
    [Parameter]
    public Option SelectedOption { get; set; } = new Option { Text = " ", Value = " " };
    [Parameter]
    public int BoxHieght { get; set; } = 5;
    [Parameter]
    public string BoxWidth { get; set; } = "auto";
    [Parameter, EditorRequired]
    public Expression<Func<string>> ValidationFor { get; set; } = default!;

    private void SelectOption(Option option)
    {
        SelectedOption = option;
    }
    protected override bool TryParseValueFromString(string value, out string result, out string validationErrorMessage)
    {
        try
        {
            result = value;
            validationErrorMessage = null;
            return true;
        }
        catch (Exception exception)
        {
            result = null;
            validationErrorMessage = exception.Message;
            return false;
        }

    }    
}

选项数据模型对象

namespace CustomComponents.DataModels
{
    public class Option
    {
        public string Text { get; set; }
        public string Value { get; set; }
    }
}

【问题讨论】:

    标签: c# validation .net-core custom-component blazor-component


    【解决方案1】:

    因为继承了组件InputBase,所以必须使用bind-value。 我编辑了很多代码以使其工作

    @using BlazorApp2.Client.Components
    @using System.Linq.Expressions
    @using System
    @using System.Collections.Generic
    @using System.Diagnostics.CodeAnalysis
    @inherits InputBase<Option>
    
    <div class="row">
        <div class="col-3">
            <select id="@Id" class="form-control" size="@BoxHieght" style="width:@BoxWidth"
            @bind="OptionValueSelected"  @bind:event="oninput">
                @foreach (var option in Options)
                {
                    <option value="@option.Value">@option.Text</option>
                }
            </select>
    
            <p>Selected option:@SelectedOption.Value </p>
        </div>
    </div>
    
    @code {
        [Parameter]
        public string Id { get; set; }
        [Parameter]
        public List<Option> Options { get; set; } = new List<Option>();
        [Parameter]
        public Option SelectedOption { get; set; } = new Option { Text = " ", Value = " " };
        [Parameter]
        public int BoxHieght { get; set; } = 5;
        [Parameter]
        public string BoxWidth { get; set; } = "auto";
        [Parameter, EditorRequired]
        public Expression<Func<string>> ValidationFor { get; set; } = default!;
    
        private string OptionValueSelected
        {
            get => CurrentValue.Value;
            set
            {
                CurrentValue = Options.Find(o => o.Value == value);
            }
        }
    
        protected override bool TryParseValueFromString(string value,
            [MaybeNullWhen(false)] out Option result, [NotNullWhen(false)] out string validationErrorMessage)
        {
            try
            {
                result = Options.First(o => o.Value == value.ToString());
                validationErrorMessage = null;
                return true;
            }
            catch (Exception exception)
            {
                result = null;
                validationErrorMessage = exception.Message;
                return false;
            }
        }
    }
    

    经过很长时间的研究,以下是我所做的一些重要更改:

    • 从类型为 Option 而非字符串的 InputBase 继承。原因:所以表单上下文知道类型并正确绑定
    • 使用设置器将值与属性绑定。原因:从字符串转换为选项
    • 从 Input base CurrectValue 中设置 SelectedOption 的值。原因:提醒表单上下文有关更改,以便更新主视图

    我在新项目中使用此页面测试了组件:

    @page "/"
    @using BlazorApp2.Client.Components
    
    <PageTitle>Index</PageTitle>
    
    @code {
        List<Option> options = new List<Option>
        {
            new Option{Text = "Test1", Value = "Test1"},
            new Option{Text = "Test2", Value = "Test2"}
        };
        ExampleModel model;
    
        protected override void OnInitialized()
        {
            model = new ExampleModel();
        }
    }
    
    <h1>Hello, world!</h1>
    
    
    <EditForm Model="@model">   
    <MyComponent Options="@options" @bind-Value="@model.Option"></MyComponent>
    </EditForm>
    <p>@model.Option.Text : @model.Option.Value</p>
    

    资源帮助我完成了研究:

    Blazor components

    Blazor form components binding

    Blazor Custom Binding

    【讨论】:

      猜你喜欢
      • 2021-07-29
      • 1970-01-01
      • 2017-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-20
      相关资源
      最近更新 更多