diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html
index 1cb1abb1185..f844fab281f 100644
--- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html
+++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html
@@ -7,13 +7,13 @@
@let showClearfix = shouldShowClearfix();
@let showErrors = shouldShowErrorMessages();
- @if (!isCheckbox && hasLabel) {
+ @if (!isCheckbox && hasLabel && !isDateField) {
+ [ngClass]="[getClass('element', 'label'), getClass('grid', 'label')]">
}
diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.spec.ts
index a89c7544377..8fb617d0336 100644
--- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.spec.ts
+++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.spec.ts
@@ -238,6 +238,8 @@ describe('DsDynamicFormControlContainerComponent test suite', () => {
const testItem: Item = new Item();
const testWSI: WorkspaceItem = new WorkspaceItem();
testWSI.item = of(createSuccessfulRemoteDataObject(testItem));
+ const renderer = jasmine.createSpyObj('Renderer2', ['setAttribute']);
+
const actions$: ReplaySubject = new ReplaySubject(1);
beforeEach(waitForAsync(() => {
@@ -303,6 +305,7 @@ describe('DsDynamicFormControlContainerComponent test suite', () => {
});
fixture.detectChanges();
+ renderer.setAttribute.calls.reset();
testElement = debugElement.query(By.css(`input[id='${testModel.id}']`));
}));
@@ -452,4 +455,43 @@ describe('DsDynamicFormControlContainerComponent test suite', () => {
});
});
+ it('should not show a label if is a checkbox or a date field', () => {
+ const checkboxLabel = fixture.debugElement.query(By.css('#label_' + formModel[0].id));
+ const dsDatePickerLabel = fixture.debugElement.query(By.css('#label_' + formModel[22].id));
+
+ expect(checkboxLabel).toBeNull();
+ expect(dsDatePickerLabel).toBeNull();
+ });
+
+ it('should not call handleAriaLabelForLibraryComponents if is SSR', () => {
+ (component as any).platformId = 'server';
+ (component as any).componentRef = {
+ instance: new DynamicNGBootstrapInputComponent(null, null),
+ location: { nativeElement: document.createElement('div') },
+ } as any;
+ fixture.detectChanges();
+
+ (component as any).handleAriaLabelForLibraryComponents();
+
+ expect(renderer.setAttribute).not.toHaveBeenCalled();
+ });
+
+ it('should set aria-label when valid input and additional property ariaLabel exist and is on browser', () => {
+ (component as any).platformId = 'browser';
+ const inputEl = document.createElement('input');
+ const hostEl = {
+ querySelector: jasmine.createSpy('querySelector').and.returnValue(inputEl),
+ };
+
+ (component as any).componentRef = {
+ instance: new DynamicNGBootstrapInputComponent(null, null),
+ location: { nativeElement: hostEl },
+ } as any;
+ (component as any).renderer = renderer;
+ component.model = { additional: { ariaLabel: 'Accessible Label' } } as any;
+ fixture.detectChanges();
+ (component as any).handleAriaLabelForLibraryComponents();
+ expect(renderer.setAttribute).toHaveBeenCalledWith(inputEl, 'aria-label', 'Accessible Label');
+ });
+
});
diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts
index cf45e8fdab7..3bdd5d67f44 100644
--- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts
+++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts
@@ -1,5 +1,6 @@
import {
AsyncPipe,
+ isPlatformBrowser,
NgClass,
NgTemplateOutlet,
} from '@angular/common';
@@ -19,7 +20,9 @@ import {
OnDestroy,
OnInit,
Output,
+ PLATFORM_ID,
QueryList,
+ Renderer2,
SimpleChanges,
Type,
ViewChild,
@@ -79,10 +82,12 @@ import {
import {
DYNAMIC_FORM_CONTROL_MAP_FN,
DYNAMIC_FORM_CONTROL_TYPE_CHECKBOX,
+ DynamicFormArrayComponent,
DynamicFormArrayGroupModel,
DynamicFormArrayModel,
DynamicFormComponentService,
DynamicFormControl,
+ DynamicFormControlComponent,
DynamicFormControlContainerComponent,
DynamicFormControlEvent,
DynamicFormControlEventType,
@@ -129,6 +134,7 @@ import { DsDynamicTypeBindRelationService } from './ds-dynamic-type-bind-relatio
import { ExistingMetadataListElementComponent } from './existing-metadata-list-element/existing-metadata-list-element.component';
import { ExistingRelationListElementComponent } from './existing-relation-list-element/existing-relation-list-element.component';
import { DYNAMIC_FORM_CONTROL_TYPE_CUSTOM_SWITCH } from './models/custom-switch/custom-switch.model';
+import { DYNAMIC_FORM_CONTROL_TYPE_DSDATEPICKER } from './models/date-picker/date-picker.model';
import { DynamicConcatModel } from './models/ds-dynamic-concat.model';
import { DsDynamicLookupRelationModalComponent } from './relation-lookup-modal/dynamic-lookup-relation-modal.component';
import { NameVariantService } from './relation-lookup-modal/name-variant.service';
@@ -227,6 +233,8 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo
@Inject(APP_CONFIG) protected appConfig: AppConfig,
@Inject(DYNAMIC_FORM_CONTROL_MAP_FN) protected dynamicFormControlFn: DynamicFormControlMapFn,
private actions$: Actions,
+ protected renderer: Renderer2,
+ @Inject(PLATFORM_ID) protected platformId: string,
) {
super(ref, componentFactoryResolver, layoutService, validationService, dynamicFormComponentService, relationService);
this.fetchThumbnail = this.appConfig.browseBy.showThumbnails;
@@ -336,6 +344,11 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo
return this.model.type === DYNAMIC_FORM_CONTROL_TYPE_CHECKBOX || this.model.type === DYNAMIC_FORM_CONTROL_TYPE_CUSTOM_SWITCH;
}
+
+ get isDateField(): boolean {
+ return this.model.type === DYNAMIC_FORM_CONTROL_TYPE_DSDATEPICKER;
+ }
+
ngOnChanges(changes: SimpleChanges) {
if (changes && !this.isRelationship && hasValue(this.group.get(this.model.id))) {
super.ngOnChanges(changes);
@@ -357,6 +370,7 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo
ngAfterViewInit() {
this.showErrorMessagesPreviousStage = this.showErrorMessages;
+ this.handleAriaLabelForLibraryComponents();
}
protected createFormControlComponent(): void {
@@ -562,6 +576,24 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo
}
}
+ private handleAriaLabelForLibraryComponents(): void {
+ if (!isPlatformBrowser(this.platformId)) {
+ return;
+ }
+
+ if ((this.componentRef.instance instanceof DynamicFormControlComponent) &&
+ !(this.componentRef.instance instanceof DynamicFormArrayComponent) &&
+ this.componentRef.location.nativeElement) {
+ const inputEl: HTMLElement | null =
+ this.componentRef.location.nativeElement.querySelector('input,textarea,select,[role="textbox"]');
+
+
+ if (inputEl && this.model?.additional?.ariaLabel) {
+ this.renderer.setAttribute(inputEl, 'aria-label', this.model.additional.ariaLabel);
+ }
+ }
+ }
+
/**
* Determines whether a form field should be validated based on its parent group's state.
* @returns {boolean} True if the field should be validated, false otherwise
diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.html
index 5d38f9e9084..3e6e05c7f74 100644
--- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.html
+++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.html
@@ -2,12 +2,12 @@