【问题标题】:Blazor: How to use the onchange event in <select> when using @bind also?Blazor:在使用 @bind 时如何在 <select> 中使用 onchange 事件?
【发布时间】:2020-01-27 06:30:46
【问题描述】:

&lt;select&gt; 中进行选择后,我需要能够运行函数。问题是我也绑定了@bind,当我尝试使用@onchange 时出现错误,指出它已被@bind 使用。我尝试使用@onselectionchange,但这什么也没做(不运行该功能)。我可能会忘记@bind,而只是将@onchange 分配给一个函数,但我不确定如何将选定的值传递给函数。

我有以下代码:

<select @bind="@SelectedCustID" @ @onchange="@CustChanged" class="form-control">
    @foreach (KeyGuidPair i in CustList)
    {
        <option value="@i.Value">@i.Text</option>
    }
</select>

谢谢。

【问题讨论】:

标签: select bind onchange blazor


【解决方案1】:
<select @bind="MyProperty">
<option>Your Option<option>
</select>

@code  {
    private string myVar;

    public string MyProperty
    {
        get { return myVar; }
        set
        {
            myVar = value;
            SomeMethod();
        }
    }

    private void SomeMethod()
    {
        //Do something
    }
}

【讨论】:

  • 这可行,但如果您需要进行一些异步调用,例如数据库更新,则会出现问题......
  • @Alexandre,我认为您可以使用 .Wait() 将异步调用转换为同步调用。见here
  • 应该选择不输入,因为用户要求选择代码。
【解决方案2】:

@bind 本质上等同于同时拥有value@onchange,例如:

<input @bind="CurrentValue" />

相当于:

<input value="@CurrentValue" @onchange="@((ChangeEventArgs e) => CurrentValue = e.Value.ToString())" />

由于您已经定义了@onchange,所以不要同时添加@bind,只需添加value 以防止冲突:

<select value="@SelectedCustID" @onchange="@CustChanged" class="form-control">
    @foreach (KeyGuidPair i in CustList)
    {
        <option value="@i.Value">@i.Text</option>
    }
</select>

来源:https://docs.microsoft.com/en-us/aspnet/core/blazor/components/data-binding?view=aspnetcore-3.1

【讨论】:

  • 只是提到你的解释,你说“相当于”帮助我弄清楚如何在 blazor select 的 onchange 事件上传递多个参数。谢谢。
【解决方案3】:

这似乎是一个普遍的困惑。首先你不能使用@onchange,因为它会被@bind在内部使用。您应该能够从 CustChanged 属性的设置器中访问选定的值。根据您尝试对 CustChanged 执行的操作,您甚至可能不需要手动检查此值何时更新。例如,如果您的意图是在您的 UI 中直接或间接使用 CustChanged(在 Linq 或其他东西中),则当您的 &lt;select&gt; 更改时,UI 将自动更新为 CustChanged 值。因此,对于大多数用例,我认为不需要检查它何时更新。

要使用@onchange,您可以将其绑定到类似这样的函数:

public void OnUpdated(ChangeEventArgs e)
{
    var selected = e.Value;
}

【讨论】:

  • 这是对所提问题的正确答案。
  • 令人讨厌的是,这似乎实际上是选择了选项文本,而不是选项值
【解决方案4】:

您可以完全避免使用@bind(如果您使用的是foreach):

<select @onchange=@(handleChange)>
    @foreach (var option in _options){
        <option value=@option.Id selected=@(SelectedId == option.Id)>@option.Name</option>
    }
</select>

@code {
    public record Person(int Id, string Name);
    public int SelectedId { get; set; }
    public List<Person> _options = new List<Person>() {
        new Person(1,"A"),
        new Person(2,"B"),
        new Person(3,"C")
    };

    public void handleChange(ChangeEventArgs args) {
        Console.WriteLine(args.Value);
        SelectedId = Int32.Parse(args.Value.ToString());
    }

}

一些肮脏的细节:在尝试将 F# 与服务器端 Blazor 一起使用时,我遇到了一些奇怪的行为。简而言之,将选项的 List 设置为实体框架查询的结果(映射到记录列表)不会正确地 @bind,而是使用 C# 类而不是 F# 记录的虚拟选项列表 确实工作。但这不是因为它是记录,因为如果我将列表设置为 EF 查询,然后立即将其设置为虚拟记录列表,它仍然没有正确地 @bind - 但它 确实 如果我注释掉 EF 行,就可以工作。

【讨论】:

【解决方案5】:

只需添加@bind-value 和@bind-vale:event 和@onchnage,如下所示。注意小写字母。这对我有用,没有任何问题。

<select @bind-value="variablenametokeepselectedvalue" @onchange="yourmethodname" @bind-value:event="oninput">
 <option value="1">Test</option>
</select>

【讨论】:

    【解决方案6】:

    请检查此示例。它正在使用 @bind 但在设置值时会触发 @onchange 事件

    <div class="form-group">
        <label for="client">Client Name</label>
        <select id="client" @bind="CheckSelected" class="form-control">
           <option value="selected1">selected1</option>
           <option value="selected2">selected2</option>
        </select>
    </div>
    
    @code {
    
        私有字符串 selectedItem {get;放;}
    
        私有字符串 CheckSelected
        {
            得到
            {
                返回选中项;
            }
            放
            {
                ChangeEventArgs selectedEventArgs = new ChangeEventArgs();
                selectedEventArgs.Value = 值;
                OnChangeSelected(selectedEventArgs);
            }
        }
    
        私人无效 OnChangeSelected(ChangeEventArgs e)
        {
            if (e.Value.ToString() != string.Empty)
            {
                selectedItem = e.Value.ToString();
            }
        }
    
    }
    

    【讨论】:

    • 值得注意的是,此解决方案适用于 blazor EditForm (stackoverflow.com/questions/61756167/…),因为 InputSelect 无法通过以下方式正确绑定事件:&lt;InputSelect Id="Source" @bind-Value="@model.Source" Class="form-control" @onchange="HandleSourceOptionChanged"&gt;
    【解决方案7】:

    如果可能,我的建议是在表单元素周围使用 EditForm 包装器。然后,您可以在一个地方检测到任何表单元素的变化。例如,这适用于一堆搜索过滤器。任何过滤器的任何更改都应触发对数据的另一次查询,等等。

    如何在表单更改时触发事件的示例在这里:

    blazor editform change events

    【讨论】:

      【解决方案8】:

      <div class="form-group">
          <label for="client">Client Name</label>
          <select class="form-control" @onchange="@((e) => { myVar = e.Value.ToString(); MyMethod(); })">
             <option value="val1">val1</option>
             <option value="val2">val2</option>
          </select>
      </div>

      这就是我在@onchange 事件中调用方法时设置属性的方式。

      -Blazor 服务器 -Dotnet Core 3.1

      【讨论】:

        【解决方案9】:

        根据Microsoft's documentation,这是他们处理此问题的首选方式:

        <InputText Value="@NewPaymentAmount" class="mdl-textfield__input"
                   ValueExpression="() => NewPaymentAmount"
                   ValueChanged="(string value) => ValidateAmount(value)" />
        
        
        
        private void ValidateAmount(string amount)
        {
            NewPaymentAmount = amount;
            
            // Do validation or whatever
        }
        

        或者async方式:

        <InputText Value="@NewPaymentAmount" class="mdl-textfield__input"
                   ValueExpression="() => NewPaymentAmount"
                   ValueChanged="async (string value) => await ValidateAmountAsync(value)" />
        
        
        
        private async Task ValidateAmountAsync(string amount)
        {
            NewPaymentAmount = amount;
            
            // Do validation or whatever
        }
        

        【讨论】:

          猜你喜欢
          • 2021-09-09
          • 1970-01-01
          • 1970-01-01
          • 2021-04-24
          • 2013-03-11
          • 2021-11-11
          • 1970-01-01
          • 2020-02-15
          • 2020-05-30
          相关资源
          最近更新 更多