自定义 Blazor 选择组件选项元素 @onclick 未触发 - 如何让它触发?

Tys*_*bby 1 .net c# html-select blazor blazor-component

我正在创建一个自定义 Blazor 组件,我需要选择组件来使用所选值更新绑定字段,这部分正在工作。我还需要它来执行从父组件传入的方法,这部分不起作用。

我能够将该方法传递到自定义组件(子组件)中,但onclick选择元素的选项元素的事件未触发。

我能够在多重选择元素中实现此功能,但它在选择元素中不起作用。

如何让它触发并仍然更新绑定的数据属性?

ESelect.razor自定义(子)选择组件

@inherits InputBase<string>

<div class="form-floating">
        <select class="form-control form-select @CssClass" id="@Id" @bind="@CurrentValue" >
            <option disabled selected></option>
            @foreach(SelectOption option in Options)
            {
                <option id=@option.Id onclick="@( () => OnClick(option) )" >@option.Value</option>
            }
        </select>
        @if (!string.IsNullOrWhiteSpace(Label))
        {
            <label class="form-control-label" for="@Id">@Label</label>        
        }
        <div class="form-control-validation">
            <ValidationMessage For="@ValidationFor" />
        </div>
</div>

Run Code Online (Sandbox Code Playgroud)

ESelect.razor.cs (ESelect.razor 的 C# 代码)

using BebComponents.DataModels;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using System.Linq.Expressions;

namespace BebComponents
{
    public partial class ESelect
    {
        [Parameter, EditorRequired]
        public Expression<Func<string>> ValidationFor { get; set; } = default!;
        [Parameter]
        public string? Id { get; set; } = "ESelect";
        [Parameter]
        public string? Label { get; set; }
        [Parameter]
        public List<SelectOption> Options { get; set; }
        [Parameter]
        public SelectOption? SelectedOption { get; set; }
        [Parameter]
        public Action? Trigger { get; set; }

        protected override bool TryParseValueFromString(string? value, out string result, out string validationErrorMessage)
        {            
            result = value; 
            validationErrorMessage = null;
            return true;
        }

        public void OnClick(SelectOption option)
        {
            SelectedOption = option;            
            Trigger?.Invoke();
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

SelectOption.cs(数据模型)

namespace BebComponents.DataModels
{
    public class SelectOption
    {
        public int Id { get; set; }
        public string Value { get; set; }
    }
}
Run Code Online (Sandbox Code Playgroud)

Index.razor

@page "/"
@using BebComponents
@using BebComponents.DataModels
@using static BebComponents.EDualSelect

<EditForm Model="Form" OnValidSubmit="ValidFormSubmit" class="mt-5">
    <DataAnnotationsValidator />
    <h3>Form Example:</h3>
    <ValidationSummary />
    <h3 class="mt-4">Enhanced Select</h3>
    <ESelect Id="ESelect" @ref="eSelect" @bind-Value="Form.LastName" Options="@options" ValidationFor="@( () => Form.LastName )" 
        Label="Last Name" Trigger="EnableEnhancedSelect2"/>
    <h5 class="mt-2">The last name selected is:</h5>
    <p>@Form.LastName</p>
</EditForm>
Run Code Online (Sandbox Code Playgroud)

Index.razor.cs

using BlazorComponents.Pages.PageModels;
using BebComponents;
using static BebComponents.EDualSelect;
using static BebComponents.ESingleSelect;
using static BebComponents.ESelect;
using BebComponents.DataModels;

namespace BlazorComponents.Pages
{    
    public partial class Index
    {
        private ESelect eSelect;
        private string eSelectResult;
        private readonly List<SelectOption> options = new List<SelectOption>
        {            
            new SelectOption { Id = 1, Value = "Jones" },
            new SelectOption { Id = 2, Value = "Smith" },
            new SelectOption { Id = 3, Value = "Bender" },
            new SelectOption { Id = 4, Value = "Baggio" },
            new SelectOption { Id = 5, Value = "Allen" },
            new SelectOption { Id = 6, Value = "Biggs" },
            new SelectOption { Id = 7, Value = "Randall" },
            new SelectOption { Id = 8, Value = "Anderson" },
            new SelectOption { Id = 8, Value = "Reeves" }
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

Rob*_*rto 5

简单的解决方案

您现有的代码只需添加一点点即可运行。

您可以在此Blazor Fiddle 演示中看到一个工作示例Blazor Fiddle 相当有限,但我尽力使代码接近原始代码。

您的点击处理程序永远不会触发,因为<option>元素仅在父元素为 时才会触发<select multiple>。然而,在这种情况下,它只是一个默认的单曲<select>,永远不会触发。我们可以使用 onchange 事件来代替,这通常是这样做的。然而,我们也可以只在 CurrentValue 属性周围添加一个包装器,这将允许您重用已有的代码。

CurrentValue 是从InputBase 继承的属性。要调用父级提供的 Trigger 方法,您需要包装 CurrentValue 以提供该新功能。这可以通过使用“new”关键字并调用 setter 中的方法来完成,如图所示。

添加到组件的代码:

[Parameter]
public new string CurrentValue 
{
    get => base.CurrentValue;
    set {
        base.CurrentValue = value;
        Trigger?.Invoke();
    }
}
Run Code Online (Sandbox Code Playgroud)

您可能还想从标记中删除现有的 onclick 处理程序,因为它不会执行任何操作并且只会产生误导。