【问题标题】:Border color not changed when field is invalid字段无效时边框颜色未更改
【发布时间】:2020-11-12 10:35:46
【问题描述】:

我对 Blazor 还很陌生。我正在尝试通过引用 this 页面在 EditForm 中呈现自定义组件。

但是当我提交没有值的表单时,边框颜色没有变为红色。此外,在清除输入值后提交表单时,边框不会变为红色。它保持绿色。

截图:

代码片段

NativeTextboxComponent.razor

<InputText @bind-Value="@Value" class="form-control" />

@code {
 public string _Value;
    [Parameter]
    public string Value
    {
        get
        {
            return _Value;
        }
        set
        {
            if (_Value != value)
            {
                ValueChanged.InvokeAsync(value);
            }
            _Value = value;
        }
    }
    [Parameter]
    public EventCallback<string> ValueChanged { get; set; }

}
}

Index.razor

<EditForm Model="@model" OnInvalidSubmit="HandleValidSubmit">
    <DataAnnotationsValidator />
    <NativeTextBoxComponent @bind-Value="@model.NativeValue"></NativeTextBoxComponent>
    <ValidationMessage For="() => model.NativeValue" />
    <button type="submit">Submit</button>
</EditForm>

public class Countries
    {
        [Required]
        public string Values { get; set; }
        [Required]
        public string LastName { get; set; }
        [Required]
        public string NativeValue { get; set; }
    }
    public Countries model = new Countries();

FieldCssClass 在这种情况下返回修改有效。

任何帮助将不胜感激。

【问题讨论】:

  • 我不确定为什么会出现这个问题,但这种情况的首选解决方案是从 InputBase 继承而不是包装 InputText

标签: c# blazor blazor-editform


【解决方案1】:

要了解为什么 FieldCssClass 返回有效而 ValidationMessage 返回无效,请务必观察您的组件 NativeTextboxComponent 对验证过程的作用。

在您的示例中,如果您将 NativeTextBoxComponent 更改为 InputText,它将正常工作。那是因为@bind-value 设置了InputBase 的ValueExpression。这个属性不是一个简单的字符串,而是一个表达式。此表达式用于从您的模型中获取属性,例如Required。

如果您使用&lt;NativeTextBoxComponent @bind-Value="@model.NativeValue"&gt;&lt;/NativeTextBoxComponent&gt;,则将一个简单的字符串绑定到组件。它已经失去了与其属性的联系。双向绑定仍然有效。如果您的组件更改了字符串,则将其写回对象。这就是你的&lt;ValidationMessage For="() =&gt; model.NativeValue" /&gt; 返回错误的原因,如果没有字符串。但同样,从嵌套的&lt;InputText @bind-Value="@Value" class="form-control" /&gt; 的角度来看,它只是一个字符串。

要解决您的问题,您的组件可以从 InputBase 继承,并且您可以创建自定义布局。

@using System.Diagnostics.CodeAnalysis;

@inherits InputBase<string>

<input @attributes="AdditionalAttributes" class="@CssClass" @bind-value="CurrentValue" />

@code {

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

【讨论】:

    【解决方案2】:

    我认为您缺少放置所需字段的模型。这是来自文档here

    的示例
    using System.ComponentModel.DataAnnotations;
    
    public class ExampleModel
    {
        [Required]
        [StringLength(10, ErrorMessage = "Name is too long.")]
        public string Name { get; set; }
    }
    

    【讨论】:

      【解决方案3】:

      ValueExpression 被定义为参数,因此父组件模型没有更新为子组件表达式,因此 FieldIdentifier cssClass 中的模型值没有更新。在editform内部渲染自定义组件时,直接调用invokeAsync和value表达式(不需要使用二绑定(@bind-Value))。

      Index.razor

      <EditForm Model="@model">
            <DataAnnotationsValidator />
            <h5>TextBox : @model.FirstName</h5>
          <NativeTextBoxComponent @bind-Value="@model.FirstName" InputHandler="@inputHandler"> </NativeTextBoxComponent >
          <ValidationMessage For="() => model.FirstName" />
         <SfButton CssClass="e-small e-info" Type="submit" Content="Submit"></SfButton>
      </EditForm>
      @code {
      public class Countries
      {
          [Required]
          public string FirstName { get; set; }
      }
      public Countries model = new Countries();
      
      private void inputHandler(ChangeEventArgs args)
      {
          model.FirstName = (string)args.Value;
      }
      
      }
      

      NativeTextboxComponent.razor

      <InputText Value="@Value" ValueChanged="ValueChanged" @oninput="@InputHandler" ValueExpression="@ValueExpression"></InputText>
      @code
      { 
      private string _value { get; set; }
      [Parameter]
      public string ID { get; set; }
      [Parameter]
      public Expression<Func<string>> ValueExpression { get; set; }
      [Parameter]
      public string Value
      {
          get => _value;
          set
          {
              if (!EqualityComparer<string>.Default.Equals(value, _value))
              {
                  _value = value;
                  ValueChanged.InvokeAsync(value);
              }
          }
      }
      [Parameter]
      public EventCallback<string> ValueChanged { get; set; }
      [Parameter]
      public EventCallback<ChangeEventArgs> InputHandler { get; set; }
      
      }
      

      【讨论】:

        【解决方案4】:

        Just the benno's answer explains exactly why you have this issue

        但是,您仍然可以使用 InputText 组件。

        相应地修改您的 NativeTextboxComponent.razor:

        <InputText Value="@Value" ValueChanged="@(v => Value = v)" ValueExpression="ValueExpression" class="form-control" />
        
        @code {
         public string _Value;
            [Parameter]
            public string Value
            {
                get
                {
                    return _Value;
                }
                set
                {
                    if (_Value != value)
                    {
                        ValueChanged.InvokeAsync(value);
                    }
                    _Value = value;
                }
            }
        
            [Parameter]
            public EventCallback<string> ValueChanged { get; set; }
        
            //Name of your property + 'Expression'
            [Parameter]
            public Expression<Func<string>> ValueExpression { get; set; }
        }
        

        【讨论】:

          猜你喜欢
          • 2018-01-14
          • 2021-11-20
          • 1970-01-01
          • 2018-10-11
          • 1970-01-01
          • 2013-02-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多