Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
578 views
in Technique[技术] by (71.8m points)

c# - 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

<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

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. So I want to make it accept DateTime and 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

question from:https://stackoverflow.com/questions/65923626/create-blazor-custom-date-picker-component-with-nullable-and-non-nullable-date-v

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Here your component with 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.

Take a look to "Option 2 (recomended): Through inheritance from InputBase "

To check i out at https://blazorrepl.com/repl/QlYPQBFj03U9ITNe13


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...