2020-04-28 15:56:56 +08:00
|
|
|
|
using System;
|
2021-01-10 13:19:07 +08:00
|
|
|
|
using System.Threading.Tasks;
|
2020-04-28 15:56:56 +08:00
|
|
|
|
using Microsoft.AspNetCore.Components;
|
2021-02-20 17:54:12 +08:00
|
|
|
|
using Microsoft.AspNetCore.Components.Web;
|
2021-04-28 11:54:19 +08:00
|
|
|
|
using Microsoft.JSInterop;
|
2020-04-28 15:56:56 +08:00
|
|
|
|
|
2020-05-29 00:33:49 +08:00
|
|
|
|
namespace AntDesign
|
2020-04-28 15:56:56 +08:00
|
|
|
|
{
|
2020-07-11 23:03:13 +08:00
|
|
|
|
public partial class DatePicker<TValue> : DatePickerBase<TValue>
|
2020-04-28 15:56:56 +08:00
|
|
|
|
{
|
2020-10-29 01:20:11 +08:00
|
|
|
|
[Parameter]
|
|
|
|
|
public EventCallback<DateTimeChangedEventArgs> OnChange { get; set; }
|
|
|
|
|
|
2021-01-10 13:19:07 +08:00
|
|
|
|
private DateTime _pickerValuesAfterInit;
|
|
|
|
|
|
2020-07-07 19:13:34 +08:00
|
|
|
|
protected override void OnInitialized()
|
|
|
|
|
{
|
|
|
|
|
base.OnInitialized();
|
2021-01-10 13:19:07 +08:00
|
|
|
|
ProcessDefaults();
|
|
|
|
|
_pickerValuesAfterInit = PickerValues[0];
|
|
|
|
|
|
|
|
|
|
}
|
2020-07-11 23:03:13 +08:00
|
|
|
|
|
2021-01-10 13:19:07 +08:00
|
|
|
|
private void ProcessDefaults()
|
|
|
|
|
{
|
|
|
|
|
UseDefaultPickerValue[0] = true;
|
|
|
|
|
if (DefaultPickerValue.Equals(default(TValue)))
|
|
|
|
|
{
|
|
|
|
|
if ((IsNullable && Value != null) || (!IsNullable && !Value.Equals(default(TValue))))
|
|
|
|
|
{
|
|
|
|
|
DefaultPickerValue = Value;
|
|
|
|
|
}
|
|
|
|
|
else if ((IsNullable && DefaultValue != null) || (!IsNullable && !DefaultValue.Equals(default(TValue))))
|
|
|
|
|
{
|
|
|
|
|
DefaultPickerValue = DefaultValue;
|
|
|
|
|
}
|
|
|
|
|
else if (!IsNullable && Value.Equals(default(TValue)))
|
|
|
|
|
{
|
|
|
|
|
DefaultPickerValue = Value;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
UseDefaultPickerValue[0] = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (UseDefaultPickerValue[0])
|
|
|
|
|
{
|
|
|
|
|
PickerValues[0] = Convert.ToDateTime(DefaultPickerValue, CultureInfo);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task OnInputClick()
|
|
|
|
|
{
|
2021-04-28 11:54:19 +08:00
|
|
|
|
if (_duringManualInput)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
AutoFocus = true;
|
2021-01-10 13:19:07 +08:00
|
|
|
|
//Reset Picker to default in case it the picker value was changed
|
|
|
|
|
//but no value was selected (for example when a user clicks next
|
|
|
|
|
//month but does not select any value)
|
|
|
|
|
if (UseDefaultPickerValue[0] && DefaultPickerValue != null)
|
|
|
|
|
{
|
|
|
|
|
PickerValues[0] = _pickerValuesAfterInit;
|
|
|
|
|
}
|
|
|
|
|
await _dropDown.Show();
|
|
|
|
|
|
|
|
|
|
// clear status
|
|
|
|
|
_pickerStatus[0]._currentShowHadSelectValue = false;
|
|
|
|
|
|
|
|
|
|
if (!_inputStart.IsOnFocused && _pickerStatus[0]._hadSelectValue && !UseDefaultPickerValue[0])
|
2020-07-07 19:13:34 +08:00
|
|
|
|
{
|
2020-07-11 23:03:13 +08:00
|
|
|
|
GetIfNotNull(Value, notNullValue =>
|
|
|
|
|
{
|
2021-01-10 13:19:07 +08:00
|
|
|
|
ChangePickerValue(notNullValue);
|
2020-07-11 23:03:13 +08:00
|
|
|
|
});
|
2020-07-07 19:13:34 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-28 11:54:19 +08:00
|
|
|
|
private TValue _cacheDuringInput;
|
|
|
|
|
|
2020-04-28 15:56:56 +08:00
|
|
|
|
protected void OnInput(ChangeEventArgs args, int index = 0)
|
|
|
|
|
{
|
2021-01-10 13:19:07 +08:00
|
|
|
|
if (index != 0)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentOutOfRangeException("DatePicker should have only single picker.");
|
|
|
|
|
}
|
2020-04-28 15:56:56 +08:00
|
|
|
|
if (args == null)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-04-28 11:54:19 +08:00
|
|
|
|
if (!_duringManualInput)
|
2020-04-28 15:56:56 +08:00
|
|
|
|
{
|
2021-04-28 11:54:19 +08:00
|
|
|
|
_duringManualInput = true;
|
|
|
|
|
_cacheDuringInput = Value;
|
|
|
|
|
}
|
|
|
|
|
if (FormatAnalyzer.TryPickerStringConvert(args.Value.ToString(), out TValue changeValue, IsNullable))
|
|
|
|
|
{
|
|
|
|
|
Value = changeValue;
|
2020-07-11 23:03:13 +08:00
|
|
|
|
GetIfNotNull(changeValue, (notNullValue) =>
|
|
|
|
|
{
|
2021-01-10 13:19:07 +08:00
|
|
|
|
PickerValues[0] = notNullValue;
|
2020-07-11 23:03:13 +08:00
|
|
|
|
});
|
2020-04-28 15:56:56 +08:00
|
|
|
|
|
2021-04-28 11:54:19 +08:00
|
|
|
|
StateHasChanged();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UpdateCurrentValueAsString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override Task OnBlur(int index)
|
|
|
|
|
{
|
|
|
|
|
if (_duringManualInput)
|
|
|
|
|
{
|
|
|
|
|
if (!Value.Equals(_cacheDuringInput))
|
2021-04-14 23:17:57 +08:00
|
|
|
|
{
|
2021-04-28 11:54:19 +08:00
|
|
|
|
//reset picker to Value
|
|
|
|
|
Value = _cacheDuringInput;
|
|
|
|
|
_pickerStatus[0]._hadSelectValue = !(Value is null && (DefaultValue is not null || DefaultPickerValue is not null));
|
|
|
|
|
GetIfNotNull(Value ?? DefaultValue ?? DefaultPickerValue, (notNullValue) =>
|
2021-04-14 23:17:57 +08:00
|
|
|
|
{
|
2021-04-28 11:54:19 +08:00
|
|
|
|
PickerValues[0] = notNullValue;
|
2021-04-14 23:17:57 +08:00
|
|
|
|
});
|
|
|
|
|
}
|
2021-04-28 11:54:19 +08:00
|
|
|
|
_duringManualInput = false;
|
2020-04-28 15:56:56 +08:00
|
|
|
|
}
|
2021-04-28 11:54:19 +08:00
|
|
|
|
if (_dropDown.IsOverlayShow())
|
|
|
|
|
Close();
|
|
|
|
|
AutoFocus = false;
|
|
|
|
|
return Task.CompletedTask;
|
2020-04-28 15:56:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-02-20 17:54:12 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Method is called via EventCallBack if the keyboard key is no longer pressed inside the Input element.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="e">Contains the key (combination) which was pressed inside the Input element</param>
|
2021-04-28 11:54:19 +08:00
|
|
|
|
protected async Task OnKeyDown(KeyboardEventArgs e)
|
2021-02-20 17:54:12 +08:00
|
|
|
|
{
|
|
|
|
|
if (e == null) throw new ArgumentNullException(nameof(e));
|
|
|
|
|
var key = e.Key.ToUpperInvariant();
|
2021-04-28 11:54:19 +08:00
|
|
|
|
if (key == "ENTER" || key == "TAB")
|
2021-02-20 17:54:12 +08:00
|
|
|
|
{
|
2021-04-28 11:54:19 +08:00
|
|
|
|
_duringManualInput = false;
|
2021-02-20 17:54:12 +08:00
|
|
|
|
if (string.IsNullOrWhiteSpace(_inputStart.Value))
|
|
|
|
|
ClearValue();
|
|
|
|
|
else
|
2021-04-28 11:54:19 +08:00
|
|
|
|
await TryApplyInputValue();
|
|
|
|
|
|
|
|
|
|
if (key == "ENTER")
|
2021-02-20 17:54:12 +08:00
|
|
|
|
{
|
2021-04-28 11:54:19 +08:00
|
|
|
|
//needed only in wasm, details: https://github.com/dotnet/aspnetcore/issues/30070
|
|
|
|
|
await Task.Yield();
|
|
|
|
|
await Js.InvokeVoidAsync(JSInteropConstants.InvokeTabKey);
|
2021-02-20 17:54:12 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (key == "ARROWDOWN" && !_dropDown.IsOverlayShow())
|
|
|
|
|
{
|
|
|
|
|
await _dropDown.Show();
|
|
|
|
|
}
|
|
|
|
|
if (key == "ARROWUP" && _dropDown.IsOverlayShow())
|
|
|
|
|
{
|
|
|
|
|
Close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-28 11:54:19 +08:00
|
|
|
|
private async Task TryApplyInputValue()
|
|
|
|
|
{
|
|
|
|
|
if (FormatAnalyzer.TryPickerStringConvert(_inputStart.Value, out TValue changeValue, IsNullable))
|
|
|
|
|
{
|
|
|
|
|
CurrentValue = changeValue;
|
|
|
|
|
GetIfNotNull(changeValue, (notNullValue) =>
|
|
|
|
|
{
|
|
|
|
|
PickerValues[0] = notNullValue;
|
|
|
|
|
});
|
|
|
|
|
if (OnChange.HasDelegate)
|
|
|
|
|
{
|
|
|
|
|
await OnChange.InvokeAsync(new DateTimeChangedEventArgs
|
|
|
|
|
{
|
|
|
|
|
Date = Convert.ToDateTime(changeValue, this.CultureInfo),
|
|
|
|
|
DateString = GetInputValue(0)
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-28 15:56:56 +08:00
|
|
|
|
/// <summary>
|
2021-01-10 13:19:07 +08:00
|
|
|
|
/// Get value of the picker
|
2020-04-28 15:56:56 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="index"></param>
|
|
|
|
|
/// <returns></returns>
|
2021-01-10 13:19:07 +08:00
|
|
|
|
public override DateTime? GetIndexValue(int index = 0)
|
2020-04-28 15:56:56 +08:00
|
|
|
|
{
|
2021-01-10 13:19:07 +08:00
|
|
|
|
if (index != 0)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentOutOfRangeException("DatePicker should have only single picker.");
|
|
|
|
|
}
|
|
|
|
|
if (_pickerStatus[0]._hadSelectValue)
|
2020-05-10 17:33:09 +08:00
|
|
|
|
{
|
2020-07-11 23:03:13 +08:00
|
|
|
|
if (Value == null)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-25 11:08:12 +08:00
|
|
|
|
return Convert.ToDateTime(Value, CultureInfo);
|
2020-05-10 17:33:09 +08:00
|
|
|
|
}
|
2021-01-10 13:19:07 +08:00
|
|
|
|
else if (DefaultValue != null)
|
2020-05-10 17:33:09 +08:00
|
|
|
|
{
|
2021-01-10 13:19:07 +08:00
|
|
|
|
return Convert.ToDateTime(DefaultValue, CultureInfo);
|
2020-05-10 17:33:09 +08:00
|
|
|
|
}
|
2020-07-11 23:03:13 +08:00
|
|
|
|
|
|
|
|
|
return null;
|
2020-04-28 15:56:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-06-01 14:09:28 +08:00
|
|
|
|
public override void ChangeValue(DateTime value, int index = 0)
|
2020-04-28 15:56:56 +08:00
|
|
|
|
{
|
2021-01-10 13:19:07 +08:00
|
|
|
|
if (index != 0)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentOutOfRangeException("DatePicker should have only single picker.");
|
|
|
|
|
}
|
|
|
|
|
UseDefaultPickerValue[0] = false;
|
2020-07-11 23:03:13 +08:00
|
|
|
|
bool result = BindConverter.TryConvertTo<TValue>(
|
|
|
|
|
value.ToString(CultureInfo), CultureInfo, out var dateTime);
|
|
|
|
|
|
|
|
|
|
if (result)
|
|
|
|
|
{
|
2020-11-18 10:43:47 +08:00
|
|
|
|
CurrentValue = dateTime;
|
2020-07-11 23:03:13 +08:00
|
|
|
|
}
|
2020-06-01 14:09:28 +08:00
|
|
|
|
|
2021-01-10 13:19:07 +08:00
|
|
|
|
_pickerStatus[0]._hadSelectValue = true;
|
2020-04-28 15:56:56 +08:00
|
|
|
|
|
2020-06-01 14:09:28 +08:00
|
|
|
|
UpdateCurrentValueAsString();
|
2020-04-28 15:56:56 +08:00
|
|
|
|
|
2020-06-01 14:09:28 +08:00
|
|
|
|
if (IsRange && !IsShowTime && Picker != DatePickerType.Time)
|
2020-04-28 15:56:56 +08:00
|
|
|
|
{
|
2020-06-01 14:09:28 +08:00
|
|
|
|
if (_pickerStatus[0]._hadSelectValue && _pickerStatus[1]._hadSelectValue)
|
2020-04-28 15:56:56 +08:00
|
|
|
|
{
|
2020-06-01 14:09:28 +08:00
|
|
|
|
Close();
|
2020-04-28 15:56:56 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2020-06-01 14:09:28 +08:00
|
|
|
|
else if (!IsShowTime && Picker != DatePickerType.Time)
|
|
|
|
|
{
|
|
|
|
|
Close();
|
|
|
|
|
}
|
2020-10-29 01:20:11 +08:00
|
|
|
|
|
|
|
|
|
if (OnChange.HasDelegate)
|
|
|
|
|
{
|
|
|
|
|
OnChange.InvokeAsync(new DateTimeChangedEventArgs
|
|
|
|
|
{
|
|
|
|
|
Date = value,
|
2021-01-10 13:19:07 +08:00
|
|
|
|
DateString = GetInputValue(0)
|
2020-10-29 01:20:11 +08:00
|
|
|
|
});
|
|
|
|
|
}
|
2020-04-28 15:56:56 +08:00
|
|
|
|
}
|
2020-07-11 23:03:13 +08:00
|
|
|
|
|
|
|
|
|
protected override void OnValueChange(TValue value)
|
|
|
|
|
{
|
|
|
|
|
base.OnValueChange(value);
|
|
|
|
|
_pickerStatus[0]._hadSelectValue = true;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-28 11:54:19 +08:00
|
|
|
|
public override void ClearValue(int index = 0, bool closeDropdown = true)
|
2020-07-06 19:09:01 +08:00
|
|
|
|
{
|
|
|
|
|
_isSetPicker = false;
|
2021-02-05 22:18:40 +08:00
|
|
|
|
|
|
|
|
|
if (!IsNullable && DefaultValue != null)
|
|
|
|
|
CurrentValue = DefaultValue;
|
|
|
|
|
else
|
|
|
|
|
CurrentValue = default;
|
2021-04-28 11:54:19 +08:00
|
|
|
|
if (closeDropdown)
|
|
|
|
|
Close();
|
2020-07-06 19:09:01 +08:00
|
|
|
|
}
|
2020-07-11 23:03:13 +08:00
|
|
|
|
|
|
|
|
|
private void GetIfNotNull(TValue value, Action<DateTime> notNullAction)
|
|
|
|
|
{
|
2021-01-10 13:19:07 +08:00
|
|
|
|
if (!IsNullable)
|
2020-07-11 23:03:13 +08:00
|
|
|
|
{
|
|
|
|
|
DateTime dateTime = Convert.ToDateTime(value, CultureInfo);
|
|
|
|
|
if (dateTime != DateTime.MinValue)
|
|
|
|
|
{
|
|
|
|
|
notNullAction?.Invoke(dateTime);
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-01-10 13:19:07 +08:00
|
|
|
|
if (IsNullable && value != null)
|
2020-07-11 23:03:13 +08:00
|
|
|
|
{
|
|
|
|
|
notNullAction?.Invoke(Convert.ToDateTime(value, CultureInfo));
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-04-28 15:56:56 +08:00
|
|
|
|
}
|
|
|
|
|
}
|