简体   繁体   English

创建具有可空和不可空日期值的 Blazor 自定义日期选择器组件

[英]Create Blazor custom date picker component with nullable and non-nullable date value

I want to create custom date picker component in Blazor. My code is like that我想在 Blazor 中创建自定义日期选择器组件。我的代码就是这样

<div class="form-group">
<label>@Title</label>
<input type="date" class="form-control" @bind="Value" />
</div>

@code{
        [Parameter]
        public string Title { get;set; }
        private DateTime? _value;
        [Parameter]
        public DateTime? Value
        {
            get
            {
                return _value;
            }
            set
            {
                if (Value == _value)
                {
                    return;
                }
                _value = value;
                ValueChanged.InvokeAsync(value);

            }
        }

        [Parameter]
        public EventCallback<DateTime?> ValueChanged { get; set; }

}

the problem is that component only works if the value is nullable DateTime (DateTime?), and if value is DateTime it throws error问题是该组件仅在值为可为空的 DateTime(DateTime?)时才有效,如果值为 DateTime,则会抛出错误

cannot convert from 'Microsoft.AspNetCore.Components.EventCallback<System.DateTime>' to 'Microsoft.AspNetCore.Components.EventCallback'

I decided to make the bind value accepts nullable because I thought it will accept both types.我决定让绑定值接受可为空,因为我认为它会接受这两种类型。 It works like that with int, double...etc.它像 int、double...等一样工作。 So I want to make it accept DateTime and DateTime?所以我想让它接受 DateTime 和 DateTime? Any ideas to make it?有什么想法吗?

Update : I tried to make the component accepts generic type but it throws error Cannot convert T to DateTime更新:我试图让组件接受通用类型,但它抛出错误Cannot convert T to DateTime

Here your component with generics:这是您的组件 generics:

@using System.Globalization
@using System

@typeparam TValue

<div class="form-group">
<label>@Title</label>
<input 
    type="date"
    class="form-control" 
    value="@FormatValueAsString(Value)"
    @onchange="@OnChange"
/>
</div>

@code {
    private const string DateFormat = "yyyy-MM-dd";
    CultureInfo provider = CultureInfo.InvariantCulture;
    private TValue _value;
    [Parameter] public string Title {get; set;}
    [Parameter] public TValue Value
    {
        get
        {
            return _value;
        }
        set
        {
            if (EqualityComparer<TValue>.Default.Equals(value , _value))
            {
                return;
            }
            _value = value;
            ValueChanged.InvokeAsync(value);

        }
    }

    [Parameter] public EventCallback<TValue> ValueChanged { get; set; }
    private void OnChange( ChangeEventArgs args)
    {
        try
        {
            Value = 
                (TValue)(object)
                DateTime
                .ParseExact(args.Value.ToString(),DateFormat, provider);
        }
        catch {
            Value = default(TValue); // not sure you want this
        }        
    }
    protected string FormatValueAsString(TValue? value)
    {
        switch (value)
        {
            case DateTime dateTimeValue:
                var r = BindConverter.FormatValue(dateTimeValue, DateFormat, provider);
                return r;
            default:
                return string.Empty; 
        }
    }    
}

But... I suggest to you to inherit from InputDate .但是......我建议你继承InputDate

Take a look to "Option 2 (recomended): Through inheritance from InputBase "查看“选项 2(推荐):通过 InputBase 的 inheritance”

To check i out at https://blazorrepl.com/repl/QlYPQBFj03U9ITNe13要检查我在https://blazorrepl.com/repl/QlYPQBFj03U9ITNe13

Much simpler way would be to inherit form Microsoft's InputDate component.更简单的方法是继承 Microsoft 的 InputDate 组件。 I have done the same to implement Bootstrap4 validation styling in Blazor, see the following snippets:我在 Blazor 中做了同样的事情来实现 Bootstrap4 验证样式,请参阅以下代码片段:

@inherits InputDate<TValue>

@typeparam TValue

<input @attributes="AdditionalAttributes"
        type="date"
        class="@Bs4InputHelpers.FixClassNames(CssClass)"
        value="@BindConverter.FormatValue(CurrentValueAsString)"
        @oninput="EventCallback.Factory.CreateBinder<string>(
    this, value => CurrentValueAsString = value, CurrentValueAsString)" />

@code {

}

And for the Helper:对于助手:

public static class Bs4InputHelpers
    {
        public static string FixClassNames(string inputClassNames)
        {
            //NOTE: Notice the space in front of the class name, this is to ensure we get
            // the suffix to our existing form-control class set from the mark up and NOT
            // half of an invalid tag.  We could use a reg-ex but that might be a bit
            // too slow for the UI rendering to stay smooth.

            // The invalid string shall always be fixed up, as we can never get it until the
            // element has checked at least once by an attempted submit.
            string result = inputClassNames.Replace(" invalid", " is-invalid");

            // The valid tag is on by default, and to keep consistency with BS4 we only want
            // it to appear either when our field is modified, or we've tried a submit
            if (inputClassNames.Contains("modified"))
            {
                result = result.Replace(" valid", " is-valid");
            }

            return result;
        }


    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM