SAP / fundamental-ngx

Fundamental Library for Angular is SAP Design System Angular component library
https://sap.github.io/fundamental-ngx
Apache License 2.0
263 stars 126 forks source link

Date Range localization validation using Dayjs Datetime Adapter not working correctly #12294

Open shamseena-dev opened 3 weeks ago

shamseena-dev commented 3 weeks ago

Is this a bug, enhancement, or feature request?

Bug

Describe your proposal.

We use Fundamental DateRange in our project extensively. We need to implement localization based on user locale. User clicking on calender (ie, calender pick) works fine and displays the date correctly in local format . However the issue is when user manually inputs the dates and validating it to the user local format in the date range (without using calender pick). Please note that the issue is for Date Range and not for single date picker.

   <fd-date-picker
      type="range"
       ......
    ></fd-date-picker>

Tried using DayJSAdapter as per documentation , however it doesn't do strict validations against the local format by default , ie, it accepts "09/03/2024 - 09.03.2024" as valid , and even "09/03/2024 - 0p9.03.2024p" is considered valid .

If using "strict" mode, the validation works as per user local, but it only accepts the input as single digit D and M (9/8/2024) and fails for double digit (Eg:09/08/2024) , while we use double digits throughout our application and hence we cant permit this strict case for consistancy reason .(Though for displaying otherwise when calender picked it was possible to fix display using the DATE_TIME_FORMATS and providing "display" format to ensure double digit display)

 providers: [
    { provide: DATE_TIME_FORMATS, useValue: CUSTOM_DAYJS_DATETIME_FORMATS },
    { provide: DatetimeAdapter, useClass: DayjsDatetimeAdapter },
    { provide: DAYJS_DATE_TIME_ADAPTER_OPTIONS, useValue: { strict: true } }
  ]

  export const getUserLocalFormat = () => {
     const userLocale = window.navigator.languages[0];
    dayjs.locale(userLocale);

    let localFormat = dayjs.localeData().longDateFormat('L');

    // Replace single digit day and month with two-digit formats
   localFormat = localFormat
  .replace(/(^|[^M])M([^M]|$)/g, '$1MM$2')  // Ensure single 'M' becomes 'MM'
  .replace(/(^|[^D])D([^D]|$)/g, '$1DD$2'); // Ensure single 'D' becomes 'DD'

   return `${localFormat}`;
 }

 export const CUSTOM_DAYJS_DATETIME_FORMATS: DateTimeFormats = {
        ...DAYJS_DATETIME_FORMATS,
        display: {
       ...DAYJS_DATETIME_FORMATS.display,
       dateInput: getUserLocalFormat()
        },
   };

Can you handle that on the application side

No

Which versions of Angular and Fundamental Library for Angular are affected? Please, specify the exact version. (If this is a feature request, use current version.)

"@angular/core": "^17.1.1",
@fundamental-ngx/core": "^0.50"

If this is a bug, please provide steps for reproducing it; the exact components you are using;

Using Date Range component and trying to implement https://sap.github.io/fundamental-ngx/#/core/dayjs-datetime-adapter for localization

Please provide relevant source code (if applicable).

       <fd-date-picker
      type="range"
      [state]="hasDateRangeFormatError ? 'error' : ''"
      [message]="getDateRangeValidationMessage()"
      fdCompact
      [(ngModel)]="dateRange.value"
      [placeholder]="dateRangePlaceholder"
      [disableFunction]="disableFunction"
      [disabled]="datePickerDisabled(filter)"
      (selectedRangeDateChange)="dateRangeChanged(filter, $event)"
      [inputId]="filter.id"
    ></fd-date-picker>

    dateRangeChanged( filter: FilterElement, event: DateRange<Dayjs>) {
       this.hasDateRangeFormatError = !Utils.isDateRangeValidOrNull(event?.start, event?.end);

       if (event?.end === null && event?.start === null) {
       filter.selected = [];
    }
   else {
      filter.selected = [{
      value: event
    }];
  }

   this.filterStateEmitter.emit(this.getSelectedValues());
 }

static isDateRangeValidOrNull1(startDate: Dayjs | null, endDate: Dayjs | null): boolean {
  // returns true if both dates are null
  if (!startDate && !endDate) {
    return true;
  }
  dayjs.locale((window.navigator.languages[0]).toLowerCase()); 
  const dateFormat = dayjs.localeData().longDateFormat('L');

  const parsedStartDate = dayjs(startDate, dateFormat, true);
  const parsedEndDate = dayjs(startDate, dateFormat, true);

  // Check if both start and end dates are valid dates
  if (startDate && parsedStartDate.isValid() && endDate && parsedEndDate.isValid()) {
    return true;
  }
  return false;
}

Please provide stackblitz example(s).

In case this is Accessibility related topic, did you consult with an accessibility expert? If not, please do so and share their recommendations.

Did you check the documentation and the API?

Yes

Did you search for similar issues?

Yes, but could not find any similar issue for date Range .

Is there anything else we should know?

Please note that issue is not for single date picker , but for Date Range.

The Date range input field is usually "startdate - enddate" format with a "-" , and sometimes it can even have hyphens within date(09-10-2024) , hence extracting the start date and end date manually considering as a string input is also challenging .

droshev commented 3 weeks ago

@dpavlenishvili Can you check this request whether we have a solution or it would require some effort?