diff --git a/CHANGELOG.md b/CHANGELOG.md
index 22a20799..8ff83171 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -80,6 +80,23 @@ so it stays clear which part of the repository actually moved.
family-wide: `true` silences every bundle loaded through this service, in every
`@dignite/ng.flex-fields*` package. (#232)
+### Fixed
+
+#### flex-fields
+
+- **`DateTimeViewComponent`, the read-only view for `DateTime` fields, ignored the field's
+ `DateTime.InputMode` configuration and always rendered `value | shortDateTime`.** A field configured
+ for `InputMode = Date` or `InputMode = Month` therefore showed a spurious time part in every
+ read-only context — a bare field, or a `Table` column rendered through `ff-table-view`, which
+ dispatches to this same component via `ff-flex-field-view`. The edit-mode counterpart,
+ `DateTimeControlComponent`, already read `configuration['DateTime.InputMode']`, looked up the
+ matching Angular `DatePipe` format string in `DATE_INPUT_MODE_FORMATS`, and formatted with it — the
+ view component never did the same lookup despite receiving the same `field.configuration` on its
+ `fields` input. `DateTimeViewComponent` now performs that lookup itself, injecting `DatePipe` the
+ same way, and falls back to the `shortDateTime` pipe only when no `fields` input is bound or the
+ configured mode isn't in the table, so existing usages that never pass `field.configuration` keep
+ rendering exactly as before.
+
## [10.0.0-rc.16] - 2026-09-05
### Fixed
diff --git a/flex-fields/angular/projects/flex-fields/src/lib/field-types/date/date-time-view.component.html b/flex-fields/angular/projects/flex-fields/src/lib/field-types/date/date-time-view.component.html
index 25875d4b..a223c75e 100644
--- a/flex-fields/angular/projects/flex-fields/src/lib/field-types/date/date-time-view.component.html
+++ b/flex-fields/angular/projects/flex-fields/src/lib/field-types/date/date-time-view.component.html
@@ -1,10 +1,10 @@
@if (showInList) {
- {{ value | shortDateTime }}
+ {{ formattedValue ?? (value | shortDateTime) }}
} @else {
-
{{ value | shortDateTime }}
+
{{ formattedValue ?? (value | shortDateTime) }}
}
diff --git a/flex-fields/angular/projects/flex-fields/src/lib/field-types/date/date-time-view.component.spec.ts b/flex-fields/angular/projects/flex-fields/src/lib/field-types/date/date-time-view.component.spec.ts
index aa45d99c..bf39757d 100644
--- a/flex-fields/angular/projects/flex-fields/src/lib/field-types/date/date-time-view.component.spec.ts
+++ b/flex-fields/angular/projects/flex-fields/src/lib/field-types/date/date-time-view.component.spec.ts
@@ -1,7 +1,36 @@
import { TestBed } from '@angular/core/testing';
import { ConfigStateService } from '@abp/ng.core';
import { CoreTestingModule } from '@abp/ng.core/testing';
+import { FlexFieldValue } from '../../models';
import { DateTimeViewComponent } from './date-time-view.component';
+import { DateTimeInputMode } from './date-time-input-mode';
+
+function fieldValue(overrides: Partial = {}): FlexFieldValue {
+ return {
+ field: {
+ id: '1',
+ name: 'publishedAt',
+ displayName: 'Published',
+ fieldTypeName: 'DateTime',
+ configuration: {},
+ },
+ required: false,
+ searchable: false,
+ ...overrides,
+ };
+}
+
+function withMode(mode: DateTimeInputMode): FlexFieldValue {
+ return fieldValue({
+ field: {
+ id: '1',
+ name: 'publishedAt',
+ displayName: 'Published',
+ fieldTypeName: 'DateTime',
+ configuration: { 'DateTime.InputMode': mode },
+ },
+ });
+}
describe('DateTimeViewComponent', () => {
beforeEach(() => {
@@ -20,22 +49,57 @@ describe('DateTimeViewComponent', () => {
} as unknown as Parameters[0]);
});
- function render(value: unknown, showInList = false) {
+ function render(value: unknown, options: { showInList?: boolean; fields?: FlexFieldValue } = {}) {
const fixture = TestBed.createComponent(DateTimeViewComponent);
fixture.componentRef.setInput('value', value);
- fixture.componentRef.setInput('showInList', showInList);
+ fixture.componentRef.setInput('showInList', options.showInList ?? false);
+ if (options.fields) {
+ fixture.componentRef.setInput('fields', options.fields);
+ }
fixture.detectChanges();
return fixture;
}
+ // Local-time construction, not an ISO `Z` string: DatePipe formats in local time, so building the
+ // expectation from the same local wall-clock value keeps the test independent of the machine's TZ.
+ const localDateTime = new Date(2026, 7, 17, 10, 30, 0);
+
it('renders nothing for an unset value instead of throwing', () => {
expect(() => render('')).not.toThrow();
});
- it('renders a formatted value both in and out of list mode', () => {
- const localDateTime = new Date(2026, 7, 17, 10, 30, 0);
+ it('falls back to the short date-time format when no configuration is available', () => {
+ expect(render(localDateTime, { showInList: true }).nativeElement.textContent).toContain('2026');
+ expect(render(localDateTime, { showInList: false }).nativeElement.textContent).toContain('2026');
+ });
+
+ it('formats the value to the Date input mode, without a time part', () => {
+ const text = render(localDateTime, { fields: withMode(DateTimeInputMode.Date) }).nativeElement.textContent;
+
+ expect(text).toContain('2026-08-17');
+ expect(text).not.toContain('10:30');
+ });
+
+ it('formats the value to the DateTime input mode', () => {
+ const text = render(localDateTime, { fields: withMode(DateTimeInputMode.DateTime) }).nativeElement.textContent;
+
+ expect(text).toContain('2026-08-17 10:30:00');
+ });
+
+ it('formats the value to the Month input mode, without a day part', () => {
+ const text = render(localDateTime, { fields: withMode(DateTimeInputMode.Month) }).nativeElement.textContent;
+
+ expect(text).toContain('2026-08');
+ expect(text).not.toContain('2026-08-17');
+ });
+
+ it('applies the configured input mode in list mode too, e.g. a Table-nested column', () => {
+ const text = render(localDateTime, {
+ showInList: true,
+ fields: withMode(DateTimeInputMode.Date),
+ }).nativeElement.textContent;
- expect(render(localDateTime, true).nativeElement.textContent).toContain('2026');
- expect(render(localDateTime, false).nativeElement.textContent).toContain('2026');
+ expect(text).toContain('2026-08-17');
+ expect(text).not.toContain('10:30');
});
});
diff --git a/flex-fields/angular/projects/flex-fields/src/lib/field-types/date/date-time-view.component.ts b/flex-fields/angular/projects/flex-fields/src/lib/field-types/date/date-time-view.component.ts
index 5c1abff4..b6ceb145 100644
--- a/flex-fields/angular/projects/flex-fields/src/lib/field-types/date/date-time-view.component.ts
+++ b/flex-fields/angular/projects/flex-fields/src/lib/field-types/date/date-time-view.component.ts
@@ -1,14 +1,24 @@
-import { Component, Input } from '@angular/core';
+import { Component, inject, Input } from '@angular/core';
import { CoreModule } from '@abp/ng.core';
+import { DatePipe } from '@angular/common';
import { FlexFieldValue } from '../../models';
+import { DATE_INPUT_MODE_FORMATS } from './date-time-configuration';
+import { DateTimeInputMode } from './date-time-input-mode';
-/** Displays the value of a `DateTime` field read-only, in the user's short date-time format. */
+/**
+ * Displays the value of a `DateTime` field read-only, formatted per its `DateTime.InputMode`
+ * configuration (mirroring `date-time-control.component.ts`'s edit-mode formatting). Falls back to
+ * the user's short date-time format when no configuration is available to read a mode from.
+ */
@Component({
selector: 'ff-date-time-view',
templateUrl: './date-time-view.component.html',
imports: [CoreModule],
+ providers: [DatePipe],
})
export class DateTimeViewComponent {
+ private readonly datePipe = inject(DatePipe);
+
/** Renders bare, without the label wrapper, for use inside a table cell. */
@Input() showInList = false;
@@ -18,4 +28,11 @@ export class DateTimeViewComponent {
@Input() type?: string;
@Input() value: unknown = '';
+
+ /** `undefined` when `fields` carries no known `InputMode`, so the template falls back to `shortDateTime`. */
+ get formattedValue(): string | null | undefined {
+ const mode = this.fields?.field.configuration['DateTime.InputMode'] as DateTimeInputMode;
+ const format = DATE_INPUT_MODE_FORMATS[mode]?.format;
+ return format ? this.datePipe.transform(this.value as string, format) : undefined;
+ }
}