onChange事件未触发Blazor InputSelect

时间:2020-05-12 15:54:57

标签: 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>

对于代码:

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);
}

当我尝试选择新项目时,不会调用RoleChange函数。有人可以指出这是怎么回事。适当值已更改,但未调用事件。

4 个答案:

答案 0 :(得分:13)

注意:

  • InputSelect是一个组件元素,而不是HTML元素,这就是为什么您不能 将其应用于@onchange编译器指令。该指令适用于 元素,通常但不一定要与value属性一起形成以下形式: 称为双向数据绑定。

  • @ bind-Value是一个编译器指令指令,指示编译器执行以下操作: 产生启用组件之间双向数据绑定的代码。正在申请 @ bind-Value到InputSelect组件需要您(已在此完成 Blazor团队的案例)来定义一个名为Value的参数属性和一个 EventCallback“委托”,通常命名为ValueChanged。价值和 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>

还有

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

您也可以按照dani herrera的建议,在模型中实现INotifyPropertyChanged.PropertyChanged事件。如果要取消使用包括EditForm在内的Forms组件,而使用常规的HTML标签,则可以这样做,在这种情况下,您可以执行以下操作:

<input type="text" value="@MyValue" @onchange=OnChange"/>

当然,您的模型类将会很厚,并且应该与EditContext进行通信...。

希望这对您有帮助...

答案 1 :(得分:1)

该请求没有那么旧,因此您可以考虑以下与EditForm一起使用的请求 (基本上连接到另一个事件)=>在oninput事件处理程序上,您传递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>

答案 2 :(得分:0)

问题是@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.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()`enter code here`
    {
        hightlight = (UserId == 3);
    }
}

答案 3 :(得分:-1)

我只是使用@onclick 事件解决了这个问题。它会触发多次,但最后一次触发时,它是所选项目。

<div>
    <EditForm Model="model">
        <InputSelect @bind-Value="model.SimulatorType" @onclick="SelectionChanged">
            @foreach (var value in Enum.GetValues(typeof(SimulatorType)))
            {
                <option>@value</option>
            }
        </InputSelect>
    </EditForm>
</div>

@code {
    class Model
    {
        public SimulatorType SimulatorType
        {
            get;set;
        }
    }

    Model model = new Model();

    private async void SelectionChanged()
    {
        await OnSelectionChanged.InvokeAsync(model.SimulatorType.ToString());
    }

    [Parameter]
    public EventCallback<string> OnSelectionChanged { get; set; }
}