From 407a64996e8d123d6c597ab38a14137ed9bb2606 Mon Sep 17 00:00:00 2001 From: Alex Molodyh <140214274+amolodyh-hyland@users.noreply.github.com> Date: Tue, 14 Jul 2026 14:54:13 -0700 Subject: [PATCH] AAE-46248 Format dropdown/radio option labels in display-text expressions (#12045) --- .../widgets/core/form-field-types.ts | 11 ++++ .../widgets/core/form-field.model.spec.ts | 22 +++++++ .../services/form-expression.service.spec.ts | 61 +++++++++++++++++++ .../form/services/form-expression.service.ts | 6 +- 4 files changed, 99 insertions(+), 1 deletion(-) diff --git a/lib/core/src/lib/form/components/widgets/core/form-field-types.ts b/lib/core/src/lib/form/components/widgets/core/form-field-types.ts index 5b5929eced..f3bc1988d6 100644 --- a/lib/core/src/lib/form/components/widgets/core/form-field-types.ts +++ b/lib/core/src/lib/form/components/widgets/core/form-field-types.ts @@ -57,6 +57,13 @@ export class FormFieldTypes { static READONLY_TYPES: string[] = [FormFieldTypes.HYPERLINK, FormFieldTypes.DISPLAY_VALUE, FormFieldTypes.READONLY_TEXT, FormFieldTypes.GROUP]; + static readonly DISPLAY_TEXT_TYPES: string[] = [ + FormFieldTypes.TEXT, + FormFieldTypes.MULTILINE_TEXT, + FormFieldTypes.READONLY_TEXT, + FormFieldTypes.DISPLAY_VALUE + ]; + static VALIDATABLE_TYPES: string[] = [FormFieldTypes.DISPLAY_EXTERNAL_PROPERTY]; static REACTIVE_TYPES: string[] = [FormFieldTypes.DATE, FormFieldTypes.DATETIME, FormFieldTypes.DROPDOWN]; @@ -67,6 +74,10 @@ export class FormFieldTypes { return FormFieldTypes.READONLY_TYPES.includes(type); } + static isDisplayTextType(type: string): boolean { + return FormFieldTypes.DISPLAY_TEXT_TYPES.includes(type); + } + static isValidatableType(type: string): boolean { return FormFieldTypes.VALIDATABLE_TYPES.includes(type); } diff --git a/lib/core/src/lib/form/components/widgets/core/form-field.model.spec.ts b/lib/core/src/lib/form/components/widgets/core/form-field.model.spec.ts index 07971a578a..25577ab99f 100644 --- a/lib/core/src/lib/form/components/widgets/core/form-field.model.spec.ts +++ b/lib/core/src/lib/form/components/widgets/core/form-field.model.spec.ts @@ -1823,3 +1823,25 @@ describe('FormFieldModel', () => { }); }); }); + +describe('FormFieldTypes', () => { + describe('isDisplayTextType', () => { + it('should return true for text, multi-line text, readonly text and display value types', () => { + expect(FormFieldTypes.isDisplayTextType(FormFieldTypes.TEXT)).toBe(true); + expect(FormFieldTypes.isDisplayTextType(FormFieldTypes.MULTILINE_TEXT)).toBe(true); + expect(FormFieldTypes.isDisplayTextType(FormFieldTypes.READONLY_TEXT)).toBe(true); + expect(FormFieldTypes.isDisplayTextType(FormFieldTypes.DISPLAY_VALUE)).toBe(true); + }); + + it('should return false for typed source field types', () => { + expect(FormFieldTypes.isDisplayTextType(FormFieldTypes.PEOPLE)).toBe(false); + expect(FormFieldTypes.isDisplayTextType(FormFieldTypes.FUNCTIONAL_GROUP)).toBe(false); + expect(FormFieldTypes.isDisplayTextType(FormFieldTypes.DROPDOWN)).toBe(false); + expect(FormFieldTypes.isDisplayTextType(FormFieldTypes.RADIO_BUTTONS)).toBe(false); + }); + + it('should return false for an unknown type', () => { + expect(FormFieldTypes.isDisplayTextType('unknown-type')).toBe(false); + }); + }); +}); diff --git a/lib/core/src/lib/form/services/form-expression.service.spec.ts b/lib/core/src/lib/form/services/form-expression.service.spec.ts index a97869de72..c4c5d59559 100644 --- a/lib/core/src/lib/form/services/form-expression.service.spec.ts +++ b/lib/core/src/lib/form/services/form-expression.service.spec.ts @@ -330,6 +330,53 @@ describe('FormExpressionService', () => { expect(result).toBe(String(date)); expect(result).not.toContain('"'); }); + + it('should format a dropdown id string to its option label', () => { + const mockField = { + id: 'dropdownField', + type: FormFieldTypes.DROPDOWN, + value: 'opt1', + options: [ + { id: 'opt1', name: 'Apple' }, + { id: 'opt2', name: 'Banana' } + ] + }; + spyOn(formModel, 'getFieldById').and.returnValue(mockField as any); + + const result = formattingService.resolveExpressions(formModel, '${field.dropdownField}'); + + expect(result).toBe('Apple'); + }); + + it('should format a radio id string to its option label', () => { + const mockField = { + id: 'radioField', + type: FormFieldTypes.RADIO_BUTTONS, + value: 'r2', + options: [ + { id: 'r1', name: 'Yes' }, + { id: 'r2', name: 'No' } + ] + }; + spyOn(formModel, 'getFieldById').and.returnValue(mockField as any); + + const result = formattingService.resolveExpressions(formModel, '${field.radioField}'); + + expect(result).toBe('No'); + }); + + it('should leave a plain string value unchanged when the source field has no formatter', () => { + const mockField = { + id: 'textField', + type: FormFieldTypes.TEXT, + value: 'plain value' + }; + spyOn(formModel, 'getFieldById').and.returnValue(mockField as any); + + const result = formattingService.resolveExpressions(formModel, '${field.textField}'); + + expect(result).toBe('plain value'); + }); }); describe('when ADF_TYPED_VALUE_FORMATTING_ENABLED token is not provided', () => { @@ -348,6 +395,20 @@ describe('FormExpressionService', () => { expect(hasFormatterSpy).not.toHaveBeenCalled(); expect(result).toBe('{"firstName":"Test","lastName":"User"}'); }); + + it('should leave a dropdown id string unchanged when formatting is disabled', () => { + const mockField = { + id: 'dropdownField', + type: FormFieldTypes.DROPDOWN, + value: 'opt1', + options: [{ id: 'opt1', name: 'Apple' }] + }; + spyOn(formModel, 'getFieldById').and.returnValue(mockField as any); + + const result = service.resolveExpressions(formModel, '${field.dropdownField}'); + + expect(result).toBe('opt1'); + }); }); describe('when escapeHtml is true', () => { diff --git a/lib/core/src/lib/form/services/form-expression.service.ts b/lib/core/src/lib/form/services/form-expression.service.ts index a9439645b0..32b1fa6d08 100644 --- a/lib/core/src/lib/form/services/form-expression.service.ts +++ b/lib/core/src/lib/form/services/form-expression.service.ts @@ -71,7 +71,7 @@ export class FormExpressionService { return ''; } - if (typeof expressionResult === 'string') { + if (typeof expressionResult === 'string' && !this.formattingEnabled) { return expressionResult; } @@ -90,6 +90,10 @@ export class FormExpressionService { return this.formFieldValueFormatter.formatValue(expressionResult, sourceField); } + if (typeof expressionResult === 'string') { + return expressionResult; + } + return this.formFieldValueFormatter.stringifyValue(expressionResult); }