onChange 事件未触发 Blazor InputSelect

Edu*_*elo 14 c# asp.net-core blazor blazor-server-side

我有以下代码用于 InputSelect

               <InputSelect class="form-control form-control form-control-sm"
                             placeholder="Role"
                             disabled="@IsReadOnly"
                             @bind-Value="Model.Role"
                              @onchange="@RoleChanged">
                    <option value="Member">Member</option>
                    <option value="Admin">Admin</option>
                    <option value="Pioner">Pioneer</option>
                    <option value="Retailer">Retailer</option>
                </InputSelect>
Run Code Online (Sandbox Code Playgroud)

对于代码:

bool ShowCreated;
bool ShowUpdated;
bool IsReadOnly;
string SelectedRole;

public EditForm AccountForm;
public Multi.Dtos.RegistrationDto Model = new Dtos.RegistrationDto() { Role = "Member" };

public void RoleChanged(ChangeEventArgs e)
{
    SelectedRole = e.Value.ToString();
    Console.WriteLine(e.Value);
}
Run Code Online (Sandbox Code Playgroud)

当我尝试选择一个新项目时,不会调用 RoleChange 函数。有人可以指出这有什么问题吗。正确的值已更改,但未调用事件。

Isa*_*aac 21

笔记:

  • InputSelect 是一个组件元素,而不是 HTML 元素,这就是为什么不能将 @onchange 编译器指令应用于它的原因。该指令应用于元素,通常但不一定与 value 属性一起形成所谓的双向数据绑定。

  • @bind-Value 是一个编译器指令指令,指示编译器生成启用组件之间双向数据绑定的代码。将 @bind-Value 应用于 InputSelect 组件需要您(在本例中已由 Blazor 团队完成)定义一个名为 Value 的参数属性和一个 EventCallback 'delegate',通常名为 ValueChanged。Value 和 ValueChanged 是 InputSelect 组件的属性。

有几种方法可以做到这一点:

 <InputSelect ValueExpression="@(()=>comment.Country)" 
                                           Value="@comment.Country" 
                 ValueChanged="@((string value) => OnValueChanged(value ))">
        <option value="">Select country...</option>
        <option value="USA">USA</option>
        <option value="Britain">Britain</option>
        <option value="Germany">Germany</option>
        <option value="Israel">Israel</option>
 </InputSelect>
Run Code Online (Sandbox Code Playgroud)

 private Task OnValueChanged(string value)
{
    // Assign the selected value to the Model 
    comment.Country = value;
   return Task.CompletedTask;
} 
Run Code Online (Sandbox Code Playgroud)

您还可以按照 dani herrera 的建议在模型中实现 INotifyPropertyChanged.PropertyChanged 事件。如果您想取消包括 EditForm 在内的 Forms 组件,而使用普通的 HTML 标签,那么您可以这样做,在这种情况下,您将能够执行以下操作:

<input type="text" value="@MyValue" @onchange=OnChange"/>
Run Code Online (Sandbox Code Playgroud)

当然你的模型类会很厚,它应该与 EditContext 通信......

希望这可以帮助...


Den*_*nes 14

问题是 @bind 属性使用 @onchange 事件,而 Blazor 不允许多个 @onchange 事件处理程序。下面代码中的解决方法:

  • 方法 1:这是普通示例。它展示了当您不需要 onchange 事件处理程序时如何使用 HTML 选择标记连接下拉列表。
  • 方法 2:我认为,如果您需要 2 路数据绑定和事件处理程序,这是最简单的方法。它使用 HTML 选择标记(不是 Blazor 组件)以及使用“value”属性的单向数据绑定。由于未使用 @bind 属性,因此我们可以自由地将处理程序附加到 @onchange 事件。该处理程序除了处理事件外,还需要填充属性以实现 2 路数据绑定。
  • 方法 3:如果您使用整个 Blazor EditForm 和 InputText/InputSelect/etc 组件基础结构,则此方法可能最适合您。如果没有 EditContext,该示例将显示使用 @bind-Value 的 2 路绑定。为了处理任何组件的 onchange 事件,我们为整个表单添加一个事件处理程序 (EditContext.OnFieldChanged)。该处理程序检查哪个属性已更改(基于 FieldName)并相应地触发所需的事件处理程序。

我创建此页面是为了提醒我相关的选项。希望它能帮助任何在这里找到路的人。

@page "/dropdown"

<h2 class='@(hightlight ? "bg-info" : "")'>
    User Id: @UserId
</h2>

<hr />

<h3>Using Select Tag</h3>
<p>
    <label>
        Method 1 (2-way binding but do not need to handle an onchange event):<br />
        <select @bind="UserId">
            <option value=""></option>
            @foreach (var u in users)
            {
                <option value="@u.Key">@u.Value</option>
            }
        </select>
    </label>
</p>
<p>
    <label>
        Method 2 (need to handle the onchange event; 2-way binding via the control onchange event handler):<br />
        <select value="@UserId" @onchange="OnChangeUserId">
            <option value=""></option>
            @foreach (var u in users)
            {
                <option value="@u.Key">@u.Value</option>
            }
        </select>
    </label>
</p>

<h3>Using InputSelect Tag</h3>
<EditForm EditContext="EditContext">
    <p>
        <label>
            Method 3 (2-way binding;  event handling via the EditForm EditContext.OnFieldChanged)<br />
            <InputSelect @bind-Value="@UserId">
                <option value=""></option>
                @foreach (var u in users)
                {
                    <option value="@u.Key">@u.Value</option>
                }
            </InputSelect>
        </label>
    </p>
</EditForm>

@code {
    private EditContext EditContext;
    private Dictionary<int, string> users = new Dictionary<int, string>();

    private int? UserId { get; set; }
    private bool hightlight { get; set; }

    protected override void OnInitialized()
    {
        EditContext = new EditContext(users);
        EditContext.OnFieldChanged += EditContext_OnFieldChanged;
    }

    protected override void OnParametersSet()
    {
        // simulate getting current data from the db (which would use async version of this event handler)
        users.Clear();
        users.Add(1, "Bob");
        users.Add(2, "Sue");
        users.Add(3, "R2D2");
        UserId = 2;

        base.OnParametersSet();
    }

    private void EditContext_OnFieldChanged(object sender, FieldChangedEventArgs e)
    {
        if (e.FieldIdentifier.FieldName == "UserId")
        {
            DoStuff();
        }
    }

    private void OnChangeUserId(ChangeEventArgs args)
    {
        // select tag's "value" attribute provide one-way data binding; to get 2-way,
        // we need to manually set the value of the UserId based on the ChangeEventArgs
        if (args.Value == null)
            UserId = null;
        else
            UserId = int.Parse(args.Value.ToString());

        DoStuff();
    }

    private void DoStuff()
    {
        hightlight = (UserId == 3);
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 8

该请求不是那么旧,因此您可以考虑以下与 EditForm 一起使用的内容(基本上连接到另一个事件)=> 在 oninput eventhandler 您传递 ChangeEventArgs var,因此您可以获得要处理的值

<InputSelect @bind-Value="@labBook.StockID" @oninput="OnLabbookStockChange" class="form-control">
                            @if (lstStocks != null)
                                {
                                <option value="">select...</option>
                                @foreach (var stock in lstStocks)
                                    {
                                    <option value="@stock.StockID">@stock.TestArticle.TAName</option>
                                    }
                                }
                        </InputSelect>
Run Code Online (Sandbox Code Playgroud)

  • 请注意,“@oninput”将在绑定模型/属性更新为所选值之前触发。您可以在“ChangedEventArgs.Value”中获取所选值 (3认同)

小智 5

使用@bind-Value:after ,如微软官方资源中所述,

对于你的例子:

               <InputSelect class="form-control form-control form-control-sm"
                         placeholder="Role"
                         disabled="@IsReadOnly"
                         @bind-Value="Model.Role"
                         @bind-Value:after="RoleChanged">
                <option value="Member">Member</option>
                <option value="Admin">Admin</option>
                <option value="Pioner">Pioneer</option>
                <option value="Retailer">Retailer</option>
            </InputSelect>
Run Code Online (Sandbox Code Playgroud)

代码:

bool ShowCreated;
bool ShowUpdated;
bool IsReadOnly;
string SelectedRole;

public EditForm AccountForm;
public Multi.Dtos.RegistrationDto Model = new Dtos.RegistrationDto() { Role = "Member" };

public void RoleChanged()
{
    Console.WriteLine(Model.Role);
}
Run Code Online (Sandbox Code Playgroud)