Skip to content

Commit ef8590f

Browse files
[DURACOM-347] refactor, fix missing label for library components
1 parent 1a4fb9f commit ef8590f

9 files changed

Lines changed: 73 additions & 10 deletions

config/config.example.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ submission:
237237
# If set to true avoid setting placeholder for simple fields, where the placeholder would be the same as the label.
238238
# The default is set to true as placeholders that do not provide additional information to the field are to be avoided as they could cause accessibility issue.
239239
# More info on the topic can be found at https://www.deque.com/blog/accessible-forms-the-problem-with-placeholders/
240-
ignorePlaceholderForSimpleFields:
240+
omitSimpleFieldPlaceholders:
241241

242242

243243
# Default Language in which the UI will be rendered if the user's browser language is not an active language

src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.spec.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,8 @@ describe('DsDynamicFormControlContainerComponent test suite', () => {
208208
const testItem: Item = new Item();
209209
const testWSI: WorkspaceItem = new WorkspaceItem();
210210
testWSI.item = of(createSuccessfulRemoteDataObject(testItem));
211+
const renderer = jasmine.createSpyObj('Renderer2', ['setAttribute']);
212+
211213
beforeEach(waitForAsync(() => {
212214

213215
TestBed.configureTestingModule({
@@ -390,4 +392,35 @@ describe('DsDynamicFormControlContainerComponent test suite', () => {
390392
expect(dsDatePickerLabel).toBeNull();
391393
});
392394

395+
it('should not call handleAriaLabelForLibraryComponents if is SSR', () => {
396+
(component as any).platformId = 'server';
397+
(component as any).componentRef = {
398+
instance: new DynamicNGBootstrapInputComponent(null, null),
399+
location: { nativeElement: document.createElement('div') },
400+
} as any;
401+
fixture.detectChanges();
402+
403+
(component as any).handleAriaLabelForLibraryComponents();
404+
405+
expect(renderer.setAttribute).not.toHaveBeenCalled();
406+
});
407+
408+
it('should set aria-label when valid input and additional property ariaLabel exist and is on browser', () => {
409+
(component as any).platformId = 'browser';
410+
const inputEl = document.createElement('input');
411+
const hostEl = {
412+
querySelector: jasmine.createSpy('querySelector').and.returnValue(inputEl),
413+
};
414+
415+
(component as any).componentRef = {
416+
instance: new DynamicNGBootstrapInputComponent(null, null),
417+
location: { nativeElement: hostEl },
418+
} as any;
419+
(component as any).renderer = renderer;
420+
component.model = { additional: { ariaLabel: 'Accessible Label' } } as any;
421+
fixture.detectChanges();
422+
(component as any).handleAriaLabelForLibraryComponents();
423+
expect(renderer.setAttribute).toHaveBeenCalledWith(inputEl, 'aria-label', 'Accessible Label');
424+
});
425+
393426
});

src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {
22
AsyncPipe,
3+
isPlatformBrowser,
34
NgClass,
45
NgTemplateOutlet,
56
} from '@angular/common';
@@ -18,7 +19,9 @@ import {
1819
OnDestroy,
1920
OnInit,
2021
Output,
22+
PLATFORM_ID,
2123
QueryList,
24+
Renderer2,
2225
SimpleChanges,
2326
Type,
2427
ViewChild,
@@ -42,6 +45,7 @@ import {
4245
DynamicFormArrayModel,
4346
DynamicFormComponentService,
4447
DynamicFormControl,
48+
DynamicFormControlComponent,
4549
DynamicFormControlContainerComponent,
4650
DynamicFormControlEvent,
4751
DynamicFormControlEventType,
@@ -122,8 +126,10 @@ import {
122126
ReorderableRelationship,
123127
} from './existing-metadata-list-element/existing-metadata-list-element.component';
124128
import { ExistingRelationListElementComponent } from './existing-relation-list-element/existing-relation-list-element.component';
129+
import { DsDynamicFormArrayComponent } from './models/array-group/dynamic-form-array.component';
125130
import { DYNAMIC_FORM_CONTROL_TYPE_CUSTOM_SWITCH } from './models/custom-switch/custom-switch.model';
126131
import { DYNAMIC_FORM_CONTROL_TYPE_DSDATEPICKER } from './models/date-picker/date-picker.model';
132+
import { DsDynamicFormGroupComponent } from './models/form-group/dynamic-form-group.component';
127133
import { DsDynamicLookupRelationModalComponent } from './relation-lookup-modal/dynamic-lookup-relation-modal.component';
128134

129135
@Component({
@@ -214,6 +220,8 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo
214220
protected metadataService: MetadataService,
215221
@Inject(APP_CONFIG) protected appConfig: AppConfig,
216222
@Inject(DYNAMIC_FORM_CONTROL_MAP_FN) protected dynamicFormControlFn: DynamicFormControlMapFn,
223+
protected renderer: Renderer2,
224+
@Inject(PLATFORM_ID) protected platformId: string,
217225
) {
218226
super(ref, componentFactoryResolver, layoutService, validationService, dynamicFormComponentService, relationService);
219227
this.fetchThumbnail = this.appConfig.browseBy.showThumbnails;
@@ -329,6 +337,7 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo
329337

330338
ngAfterViewInit() {
331339
this.showErrorMessagesPreviousStage = this.showErrorMessages;
340+
this.handleAriaLabelForLibraryComponents();
332341
}
333342

334343
protected createFormControlComponent(): void {
@@ -470,4 +479,23 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo
470479
this.subs.push(collection$.subscribe((collection) => this.collection = collection));
471480

472481
}
482+
483+
private handleAriaLabelForLibraryComponents(): void {
484+
if (!isPlatformBrowser(this.platformId)) {
485+
return;
486+
}
487+
488+
if ((this.componentRef.instance instanceof DynamicFormControlComponent) &&
489+
!(this.componentRef.instance instanceof DsDynamicFormArrayComponent) &&
490+
!(this.componentRef.instance instanceof DsDynamicFormGroupComponent) &&
491+
this.componentRef.location.nativeElement) {
492+
const inputEl: HTMLElement | null =
493+
this.componentRef.location.nativeElement.querySelector('input,textarea,select,[role="textbox"]');
494+
495+
496+
if (inputEl && this.model?.additional?.ariaLabel) {
497+
this.renderer.setAttribute(inputEl, 'aria-label', this.model.additional.ariaLabel);
498+
}
499+
}
500+
}
473501
}

src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
class="form-control"
4242
[attr.aria-labelledby]="'label_' + model.id"
4343
[attr.autoComplete]="model.autoComplete"
44-
[attr.aria-label]="model.label | translate"
44+
[attr.aria-label]="(model.label || model?.additional?.ariaLabel) | translate"
4545
[class.is-invalid]="showErrorMessages"
4646
[id]="model.id"
4747
[inputFormatter]="formatter"

src/app/shared/form/builder/parsers/date-field-parser.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ describe('DateFieldParser test suite', () => {
6868
expect(fieldModel.value).toEqual(expectedValue);
6969
});
7070

71-
it('should skip setting the placeholder when ignore ignorePlaceholderForSimpleFields is true', () => {
71+
it('should skip setting the placeholder when ignore omitSimpleFieldPlaceholders is true', () => {
7272
const parser = new DateFieldParser(submissionId, field, initFormValues, parserOptions, translateService);
73-
parser.ignorePlaceholderForSimpleFields = true;
73+
parser.omitSimpleFieldPlaceholders = true;
7474
const fieldModel = parser.parse();
7575

7676
expect(fieldModel.placeholder).toBeNull();

src/app/shared/form/builder/parsers/field-parser.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export abstract class FieldParser {
5454
*/
5555
protected typeField: string;
5656

57-
ignorePlaceholderForSimpleFields: boolean;
57+
omitSimpleFieldPlaceholders: boolean;
5858

5959
constructor(
6060
@Inject(SUBMISSION_ID) protected submissionId: string,
@@ -63,7 +63,7 @@ export abstract class FieldParser {
6363
@Inject(PARSER_OPTIONS) protected parserOptions: ParserOptions,
6464
protected translate: TranslateService,
6565
) {
66-
this.ignorePlaceholderForSimpleFields = environment.submission.ignorePlaceholderForSimpleFields;
66+
this.omitSimpleFieldPlaceholders = environment.submission.omitSimpleFieldPlaceholders;
6767
}
6868

6969
public abstract modelFactory(fieldValue?: FormFieldMetadataValueObject, label?: boolean): any;
@@ -310,8 +310,10 @@ export abstract class FieldParser {
310310
if (hint) {
311311
controlModel.hint = this.configData.hints || ' ';
312312
}
313-
if (!this.ignorePlaceholderForSimpleFields) {
313+
if (!this.omitSimpleFieldPlaceholders) {
314314
controlModel.placeholder = this.configData.label;
315+
} else {
316+
controlModel.additional = { ...controlModel.additional, ariaLabel: this.configData.label };
315317
}
316318

317319
if (this.configData.mandatory && setErrors) {

src/config/default-app-config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ export class DefaultAppConfig implements AppConfig {
251251
],
252252
},
253253
},
254-
ignorePlaceholderForSimpleFields: true,
254+
omitSimpleFieldPlaceholders: true,
255255
};
256256

257257
// Default Language in which the UI will be rendered if the user's browser language is not an active language

src/config/submission-config.interface.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,5 @@ export interface SubmissionConfig extends Config {
3636
duplicateDetection: DuplicateDetectionConfig;
3737
typeBind: TypeBindConfig;
3838
icons: IconsConfig;
39-
ignorePlaceholderForSimpleFields?: boolean;
39+
omitSimpleFieldPlaceholders?: boolean;
4040
}

src/environments/environment.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ export const environment: BuildConfig = {
195195
],
196196
},
197197
},
198-
ignorePlaceholderForSimpleFields: false,
198+
omitSimpleFieldPlaceholders: false,
199199
},
200200

201201
// NOTE: will log all redux actions and transfers in console

0 commit comments

Comments
 (0)