【问题标题】:Blazor InputText call async Method when TextChangedBlazor InputText 在 TextChanged 时调用 async 方法
【发布时间】:2020-09-24 16:57:21
【问题描述】:

我尝试在 Blazor (ServerSide) 中捕获 InputText 的文本更改,然后调用异步方法检查输入的优惠券代码是否正确。

HTML:

<EditForm Model="@Basket" OnValidSubmit="@CommitBasket">
    Gutscheincode
    <InputText class="coupon-input checkout-control pristine untouched" 
            @bind-Value="CouponCode"
            @onchange="CouponCodeChanged">
    </InputText>
    @CouponText
</EditForm>`

但 CouponCodeChanged 未引发 - OnKeyUp 没有用,因为在该状态下文本值未更改...

这里是 C# 方法:

public async Task CouponCodeChanged(ChangeEventArgs args)
{
    using var client = ClientFactory.CreateClient();
    var result = await ApiCalls.GetCouponCodeData(client, AppState.BaseUrl, 2, CouponCode);
    CouponText = result== null ? "NOT FOUND" : $"exists:{result.Exists} amount:{result.Amount}";
}

有没有人提示或想法如何以方便的方式解决这个问题?

谢谢!

【问题讨论】:

标签: blazor


【解决方案1】:

InputText 组件没有onchange 事件但ValueChanged
然而,如果你想订阅这个事件,你需要传递一个ValueExpression,这并不容易。 我发现订阅此事件的最简单方法是覆盖 InputText 组件。

CouponComponent.razor

@inherits InputText
<InputText class="coupon-input checkout-control pristine untouched" 
                   ValueExpression="ValueExpression" Value="@Value" ValueChanged="OnValueChanged" />
@code {
  [Parameter]
  public EventCallback<string> CouponValueChanged { get; set; }

  private async Task OnValueChanged(string value)
  {
     await ValueChanged.InvokeAsync(value);
     using var client = ClientFactory.CreateClient();
     var result = await ApiCalls.GetCouponCodeData(client, AppState.BaseUrl, 2, CouponCode);
     var coupon = result == null ? "NOT FOUND" : $"exists:{result.Exists} amount:{result.Amount}"
     await CouponValueChanged.InvokeAsync(coupon);
  }
}

用法

<EditForm Model="@Basket" OnValidSubmit="@CommitBasket">
    Gutscheincode
    <CouponComponent @bind-Value="CouponCode"
        @CouponValueChanged="CouponCodeChanged">
    </InputText>
    @CouponText
</EditForm>

@code {
   private void CouponCodeChanged(string coupon)
   {
      CouponText = coupon;
      StateHasChanged();
   }
}

【讨论】:

    【解决方案2】:

    这对我有用...

    @using System.Linq.Expressions 
    
       <p>@Coupon Text: @CouponText</p>
    
    
    
        <EditForm Model="@basket" OnValidSubmit="@CommitBasket">
            Gutscheincode
    
                <InputText class="coupon-input checkout-control pristine untouched" Value="@basket.CouponCode" ValueChanged="@CouponCodeChanged" ValueExpression="@(() => basket.CouponCode)" />
    
        </EditForm>
    
        @code {
            private Basket basket = new Basket();
            private string CouponText;
    
            private string _value { get; set; }
            [Parameter]
            public string Value
            {
                get { return _value; }
                set
                {
                    if (_value != value)
                    {
                        _value = value;
                        if (ValueChanged.HasDelegate)
                        {
                            ValueChanged.InvokeAsync(value);
                        }
                    }
    
    
                }
            }
    
            [Parameter] public EventCallback<string> ValueChanged { get; set; }
            [Parameter] public Expression<Func<string>> ValueExpression { get; set; }
    
    
            private void CouponCodeChanged(string CouponCode)
            {
                basket.CouponCode = CouponCode;
                CouponText =  basket.CouponCode;
            }
    
            private void CommitBasket()
            { }
    
            public class Basket
            {
                public Basket() { }
                public string CouponCode { get; set; } = "12345";
                public string CouponName { get; set; } = "Coupon Name";
    
            }
        }
    

    您也可以通过 KeyUp 事件来做到这一点:

    <InputText Id="CouponCode" Class="form-control" @bind-Value="@basket.CouponCode" @onkeyup='@(e => KeyUp(e, "CouponCode"))'></InputText>
    
    
    @code {
        private EditContext EditContext;
        private Basket basket = new Basket();
    
         protected override void OnInitialized()
        {
            EditContext = new EditContext(basket);
            base.OnInitialized();
        }
    
        void KeyUp(KeyboardEventArgs e, string memberName)
        {
            var property = basket.GetType().GetProperty(memberName);
            var value = property.GetValue(basket);
    
            // Requires some tweaks to prevent unwanted stuff...
            property.SetValue(basket, value + e.Key);
    
            var id = EditContext.Field(memberName);
    
    
            EditContext.NotifyFieldChanged(id);
            property = basket.GetType().GetProperty(memberName);
    
            CouponText = property.GetValue(basket).ToString();
    
        }
    }
    

    【讨论】:

      【解决方案3】:

      试试这个:

      @onchange="(ChangeEventArgs _event) =&gt; CouponCodeChanged(_event.Value.ToString())"

      更新方法:

      public async Task CouponCodeChanged(string coupon)
      ...
      ..., AppState.BaseUrl, 2, coupon);
      ...
      

      【讨论】:

        【解决方案4】:

        我创建了一组Blazor components。其中之一是Debounced inputs,具有多种输入类型和更多功能。 Blazor.Components.Debounce.Input 在NuGet 上可用。

        您可以通过demo app 试用。

        注意:目前它处于预览状态。最终版本将随 .NET 5 一起发布。发布

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-10-30
          • 2019-01-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多