diff --git a/projects/composition/src/app/pages/autocomplete-page/autocomplete-page.component.html b/projects/composition/src/app/pages/autocomplete-page/autocomplete-page.component.html
index 13e8951a5..b51048c77 100644
--- a/projects/composition/src/app/pages/autocomplete-page/autocomplete-page.component.html
+++ b/projects/composition/src/app/pages/autocomplete-page/autocomplete-page.component.html
@@ -215,6 +215,21 @@
+
+
+
+
+
option.data.code;
+
get availableOptionInfo() {
return this.options.map((option) => option.name).join(', ');
}
diff --git a/projects/composition/src/app/pages/autocomplete-page/autocomplete-page.examples.ts b/projects/composition/src/app/pages/autocomplete-page/autocomplete-page.examples.ts
index 31d2417d4..49c37c629 100644
--- a/projects/composition/src/app/pages/autocomplete-page/autocomplete-page.examples.ts
+++ b/projects/composition/src/app/pages/autocomplete-page/autocomplete-page.examples.ts
@@ -236,6 +236,23 @@ syncVal: string[] = [];`
ts: citiesOptionsTs
},
+ functionOptionKey: {
+ html: `
+
+`,
+ ts: `
+${citiesOptionsTs.trim()}
+
+getCode = (option: any): string => option.data.code;`
+ },
+
asyncValidation: {
html: `
- {{ syncVal }}
+ [value]="[options[0].data, options[4].data]">
+
+
+
+
+
+
+ {{ syncVal }}
+
+
+
+
+
+
+
diff --git a/projects/composition/src/app/pages/select-page/select-page.component.ts b/projects/composition/src/app/pages/select-page/select-page.component.ts
index ae3bce6e0..2aa137661 100644
--- a/projects/composition/src/app/pages/select-page/select-page.component.ts
+++ b/projects/composition/src/app/pages/select-page/select-page.component.ts
@@ -63,6 +63,8 @@ export class SelectPageComponent implements OnInit {
openOnClearValue = this.options[3];
componentData = ComponentData;
+ getCode = (option: any): string => option.data.code;
+
// eslint-disable-next-line no-useless-constructor
constructor(private _formBuilder: UntypedFormBuilder) {}
diff --git a/projects/composition/src/app/pages/tree-autocomplete-page/tree-autocomplete-page.component.html b/projects/composition/src/app/pages/tree-autocomplete-page/tree-autocomplete-page.component.html
index cbb019e06..6318f369c 100644
--- a/projects/composition/src/app/pages/tree-autocomplete-page/tree-autocomplete-page.component.html
+++ b/projects/composition/src/app/pages/tree-autocomplete-page/tree-autocomplete-page.component.html
@@ -122,8 +122,78 @@
optionInfo="attrType"
optionLabel="label"
[clearable]="true"
- [(ngModel)]="syncVal"
- [ngModelOptions]="{ standalone: true }">
+ [persistentClear]="true"
+ [virtualScroll]="true"
+ [multiple]="true">
+
+
+
+
+
+
+
+
+
+
+ {{ syncVal?.label }}
+
+
+
+
+
+
+
+
{{ syncVal?.label }}
diff --git a/projects/composition/src/app/pages/tree-autocomplete-page/tree-autocomplete-page.component.ts b/projects/composition/src/app/pages/tree-autocomplete-page/tree-autocomplete-page.component.ts
index db3aa9fed..43ed15971 100644
--- a/projects/composition/src/app/pages/tree-autocomplete-page/tree-autocomplete-page.component.ts
+++ b/projects/composition/src/app/pages/tree-autocomplete-page/tree-autocomplete-page.component.ts
@@ -127,6 +127,9 @@ export class TreeAutocompletePageComponent implements OnInit {
componentData = ComponentData;
+ getLabel = (option: any): string =>
+ option.label + (option.attrType ? ` (${option.attrType})` : '');
+
// eslint-disable-next-line no-useless-constructor
constructor(private _formBuilder: UntypedFormBuilder) {}
diff --git a/projects/composition/src/app/pages/tree-select-page/tree-select-page.component.html b/projects/composition/src/app/pages/tree-select-page/tree-select-page.component.html
index 6e8dae9b9..c4110aff4 100644
--- a/projects/composition/src/app/pages/tree-select-page/tree-select-page.component.html
+++ b/projects/composition/src/app/pages/tree-select-page/tree-select-page.component.html
@@ -122,8 +122,76 @@
optionInfo="attrType"
optionLabel="label"
[clearable]="true"
- [(ngModel)]="syncVal"
- [ngModelOptions]="{ standalone: true }">
+ [persistentClear]="true"
+ [virtualScroll]="true"
+ [multiple]="true">
+
+
+
+
+
+
+
+
+
+
+ {{ syncVal?.label }}
+
+
+
+
+
+
+
+
{{ syncVal?.label }}
diff --git a/projects/composition/src/app/pages/tree-select-page/tree-select-page.component.ts b/projects/composition/src/app/pages/tree-select-page/tree-select-page.component.ts
index 89953b611..98d444f89 100644
--- a/projects/composition/src/app/pages/tree-select-page/tree-select-page.component.ts
+++ b/projects/composition/src/app/pages/tree-select-page/tree-select-page.component.ts
@@ -127,6 +127,9 @@ export class TreeSelectPageComponent implements OnInit {
componentData = ComponentData;
+ getLabel = (option: any): string =>
+ option.label + (option.attrType ? ` (${option.attrType})` : '');
+
// eslint-disable-next-line no-useless-constructor
constructor(private _formBuilder: UntypedFormBuilder) {}
diff --git a/projects/cps-ui-kit/src/lib/components/cps-autocomplete/cps-autocomplete.component.html b/projects/cps-ui-kit/src/lib/components/cps-autocomplete/cps-autocomplete.component.html
index 56ab52767..413d984ee 100644
--- a/projects/cps-ui-kit/src/lib/components/cps-autocomplete/cps-autocomplete.component.html
+++ b/projects/cps-ui-kit/src/lib/components/cps-autocomplete/cps-autocomplete.component.html
@@ -58,7 +58,7 @@
data-testid="cps-autocomplete-selected-value">
{{
returnObject
- ? value[optionLabel]
+ ? getProp(value, optionLabel)
: (value
| labelByValue: options : optionValue : optionLabel)
}}
@@ -95,7 +95,7 @@
}">
{{
returnObject
- ? val[optionLabel]
+ ? getProp(val, optionLabel)
: (val
| labelByValue
: options
@@ -137,7 +137,7 @@
}"
[label]="
returnObject
- ? val[optionLabel]
+ ? getProp(val, optionLabel)
: (val
| labelByValue: options : optionValue : optionLabel)
">
@@ -402,14 +402,14 @@
data-testid="cps-autocomplete-options"
class="cps-autocomplete-options-option-label"
[class.virtual-row]="virtualScroll"
- >{{ item[optionLabel] }}{{ getProp(item, optionLabel) }}
{{ item[optionInfo] }}{{ getProp(item, optionInfo) }}
diff --git a/projects/cps-ui-kit/src/lib/components/cps-autocomplete/cps-autocomplete.component.spec.ts b/projects/cps-ui-kit/src/lib/components/cps-autocomplete/cps-autocomplete.component.spec.ts
index 7b659ba26..0da1690a1 100644
--- a/projects/cps-ui-kit/src/lib/components/cps-autocomplete/cps-autocomplete.component.spec.ts
+++ b/projects/cps-ui-kit/src/lib/components/cps-autocomplete/cps-autocomplete.component.spec.ts
@@ -464,6 +464,88 @@ describe('CpsAutocompleteComponent', () => {
expect(component.filteredOptions.length).toBe(3);
});
+ describe('function-based option keys', () => {
+ const nestedOptions = [
+ { meta: { title: 'Alpha', id: 1 } },
+ { meta: { title: 'Beta', id: 2 } },
+ { meta: { title: 'Gamma', id: 3 } }
+ ];
+
+ it('getProp should return property value when key is a string', () => {
+ expect(component.getProp({ label: 'hello' }, 'label')).toBe('hello');
+ });
+
+ it('getProp should invoke the function and return its result when key is a function', () => {
+ const fn = (o: any) => o.meta.title;
+ expect(component.getProp({ meta: { title: 'hello' } }, fn)).toBe('hello');
+ });
+
+ it('should display selected label using function optionLabel', () => {
+ fixture.componentRef.setInput('options', nestedOptions);
+ fixture.componentRef.setInput('optionLabel', (o: any) => o.meta.title);
+ component.value = nestedOptions[0];
+ fixture.changeDetectorRef.markForCheck();
+ fixture.detectChanges();
+ const selectedLabel = fixture.debugElement.query(
+ By.css('.single-item-selection span')
+ );
+ expect(selectedLabel.nativeElement.textContent.trim()).toBe('Alpha');
+ });
+
+ it('should filter options using function optionLabel', fakeAsync(() => {
+ fixture.componentRef.setInput('options', nestedOptions);
+ fixture.componentRef.setInput('optionLabel', (o: any) => o.meta.title);
+ fixture.detectChanges();
+ const inputElement = fixture.debugElement.query(
+ By.css('.cps-autocomplete-box-input')
+ );
+ inputElement.nativeElement.value = 'bet';
+ inputElement.nativeElement.dispatchEvent(new Event('input'));
+ fixture.detectChanges();
+ tick(component.inputChangeDebounceTime);
+ fixture.detectChanges();
+ expect(component.filteredOptions.length).toBe(1);
+ expect(component.filteredOptions[0]).toBe(nestedOptions[1]);
+ }));
+
+ it('should emit the function-derived value when optionValue is a function and returnObject is false', () => {
+ fixture.componentRef.setInput('options', nestedOptions);
+ fixture.componentRef.setInput('optionLabel', (o: any) => o.meta.title);
+ fixture.componentRef.setInput('optionValue', (o: any) => o.meta.id);
+ fixture.componentRef.setInput('returnObject', false);
+ fixture.detectChanges();
+ jest.spyOn(component.valueChanged, 'emit');
+ component.select(nestedOptions[1], false);
+ expect(component.valueChanged.emit).toHaveBeenCalledWith(2);
+ });
+
+ it('should collect all function-derived values when toggleAll is called with returnObject false', () => {
+ fixture.componentRef.setInput('options', nestedOptions);
+ fixture.componentRef.setInput('optionLabel', (o: any) => o.meta.title);
+ fixture.componentRef.setInput('optionValue', (o: any) => o.meta.id);
+ fixture.componentRef.setInput('returnObject', false);
+ fixture.componentRef.setInput('multiple', true);
+ component.value = [];
+ fixture.changeDetectorRef.markForCheck();
+ fixture.detectChanges();
+ component.toggleAll();
+ expect(component.value).toEqual([1, 2, 3]);
+ });
+
+ it('should display chips with labels from function optionLabel', () => {
+ fixture.componentRef.setInput('options', nestedOptions);
+ fixture.componentRef.setInput('optionLabel', (o: any) => o.meta.title);
+ fixture.componentRef.setInput('multiple', true);
+ component.value = [nestedOptions[0], nestedOptions[2]];
+ fixture.changeDetectorRef.markForCheck();
+ fixture.detectChanges();
+ const chipElements = fixture.debugElement.queryAll(By.css('cps-chip'));
+ expect(chipElements.length).toBe(2);
+ expect(chipElements[0].nativeElement.textContent.trim()).toBe('Alpha');
+ expect(chipElements[1].nativeElement.textContent.trim()).toBe('Gamma');
+ });
+ });
+
describe('Scroll alignment', () => {
let scrollIntoView: jest.Mock;
diff --git a/projects/cps-ui-kit/src/lib/components/cps-autocomplete/cps-autocomplete.component.ts b/projects/cps-ui-kit/src/lib/components/cps-autocomplete/cps-autocomplete.component.ts
index 2f074fefc..5091cb0eb 100644
--- a/projects/cps-ui-kit/src/lib/components/cps-autocomplete/cps-autocomplete.component.ts
+++ b/projects/cps-ui-kit/src/lib/components/cps-autocomplete/cps-autocomplete.component.ts
@@ -42,6 +42,7 @@ import { LabelByValuePipe } from '../../pipes/internal/label-by-value/label-by-v
import { CheckOptionSelectedPipe } from '../../pipes/internal/check-option-selected/check-option-selected.pipe';
import { isEqual } from 'lodash-es';
import { CpsTooltipPosition } from '../../directives/cps-tooltip/cps-tooltip.directive';
+import { getOptionProp, OptionKey } from '../../utils/internal/option-utils';
import {
CpsMenuComponent,
CpsMenuHideReason
@@ -192,22 +193,22 @@ export class CpsAutocompleteComponent
@Input() keepInitialOrder = false;
/**
- * Name of the label field of an option.
+ * Name of the label field of an option, or a function that receives the option and returns the label.
* @group Props
*/
- @Input() optionLabel = 'label';
+ @Input() optionLabel: OptionKey = 'label';
/**
- * Name of the value field of an option. Needed only if returnObject prop is false.
+ * Name of the value field of an option, or a function that receives the option and returns the value. Needed only if returnObject prop is false.
* @group Props
*/
- @Input() optionValue = 'value';
+ @Input() optionValue: OptionKey = 'value';
/**
- * Name of the info field of an option, shows the additional information text.
+ * Name of the info field of an option, or a function that receives the option and returns the info text.
* @group Props
*/
- @Input() optionInfo = 'info';
+ @Input() optionInfo: OptionKey = 'info';
/**
* Hides hint and validation errors.
@@ -557,6 +558,10 @@ export class CpsAutocompleteComponent
this._destroy$.complete();
}
+ getProp(option: any, key: OptionKey): any {
+ return getOptionProp(option, key);
+ }
+
select(
option: any,
byValue: boolean,
@@ -572,7 +577,7 @@ export class CpsAutocompleteComponent
? option
: this.returnObject
? option
- : option[this.optionValue];
+ : getOptionProp(option, this.optionValue);
if (this.multiple) {
let res = [];
if (includes(this.value, val)) {
@@ -580,7 +585,9 @@ export class CpsAutocompleteComponent
} else {
if (this.keepInitialOrder) {
this.options.forEach((o) => {
- const ov = this.returnObject ? o : o[this.optionValue];
+ const ov = this.returnObject
+ ? o
+ : getOptionProp(o, this.optionValue);
if (
this.value.some((v: any) => isEqual(v, ov)) ||
isEqual(val, ov)
@@ -590,12 +597,15 @@ export class CpsAutocompleteComponent
});
} else {
const opt = this.options.find((o) => {
- return isEqual(val, this.returnObject ? o : o[this.optionValue]);
+ return isEqual(
+ val,
+ this.returnObject ? o : getOptionProp(o, this.optionValue)
+ );
});
if (opt) {
res = [
...this.value,
- this.returnObject ? opt : opt[this.optionValue]
+ this.returnObject ? opt : getOptionProp(opt, this.optionValue)
];
}
}
@@ -628,7 +638,7 @@ export class CpsAutocompleteComponent
res = this.options;
} else {
this.options.forEach((o) => {
- res.push(o[this.optionValue]);
+ res.push(getOptionProp(o, this.optionValue));
});
}
}
@@ -664,7 +674,9 @@ export class CpsAutocompleteComponent
this.backspaceClickedOnce = false;
let _filteredOptions = this.options.filter((o: any) => {
- let res = o[this.optionLabel].toLowerCase().includes(searchVal);
+ let res = (getOptionProp(o, this.optionLabel) || '')
+ .toLowerCase()
+ .includes(searchVal);
if (
!res &&
this.withOptionsAliases &&
@@ -950,7 +962,7 @@ export class CpsAutocompleteComponent
? undefined
: this.returnObject
? option
- : option[this.optionValue];
+ : getOptionProp(option, this.optionValue);
}
private _toggleOptions(show?: boolean): void {
@@ -1036,7 +1048,7 @@ export class CpsAutocompleteComponent
private _getValueLabel() {
return this.hasSelectedValue()
? this.returnObject
- ? this.value[this.optionLabel]
+ ? getOptionProp(this.value, this.optionLabel)
: this._labelByValue.transform(
this.value,
this.options,
@@ -1210,7 +1222,8 @@ export class CpsAutocompleteComponent
}
const found = this.filteredOptions.find(
- (o: any) => o[this.optionLabel].toLowerCase() === searchVal
+ (o: any) =>
+ (getOptionProp(o, this.optionLabel) || '').toLowerCase() === searchVal
);
if (found) {
this.select(found, false, true, needFocusInput);
diff --git a/projects/cps-ui-kit/src/lib/components/cps-select/cps-select.component.html b/projects/cps-ui-kit/src/lib/components/cps-select/cps-select.component.html
index 4f747f568..c0ec7a348 100644
--- a/projects/cps-ui-kit/src/lib/components/cps-select/cps-select.component.html
+++ b/projects/cps-ui-kit/src/lib/components/cps-select/cps-select.component.html
@@ -71,7 +71,7 @@
{{
returnObject
- ? value[optionLabel]
+ ? getProp(value, optionLabel)
: (value
| labelByValue: options : optionValue : optionLabel)
}}
@@ -295,14 +295,14 @@
class="cps-select-options-option-label"
data-testid="cps-select-option-label"
[class.virtual-row]="virtualScroll"
- >{{ item[optionLabel] }}{{ getProp(item, optionLabel) }}
- {{ item[optionInfo] }}
+ {{ getProp(item, optionInfo) }}
@if (item[optionIcon]) {
isEqual(item, val)) || false;
@@ -493,7 +498,7 @@ export class CpsSelectComponent
? option
: this.returnObject
? option
- : option[this.optionValue];
+ : getOptionProp(option, this.optionValue);
if (this.multiple) {
let res = [];
if (includes(this.value, val)) {
@@ -501,7 +506,9 @@ export class CpsSelectComponent
} else {
if (this.keepInitialOrder) {
this.options.forEach((o) => {
- const ov = this.returnObject ? o : o[this.optionValue];
+ const ov = this.returnObject
+ ? o
+ : getOptionProp(o, this.optionValue);
if (
this.value.some((v: any) => isEqual(v, ov)) ||
isEqual(val, ov)
@@ -511,12 +518,15 @@ export class CpsSelectComponent
});
} else {
const opt = this.options.find((o) => {
- return isEqual(val, this.returnObject ? o : o[this.optionValue]);
+ return isEqual(
+ val,
+ this.returnObject ? o : getOptionProp(o, this.optionValue)
+ );
});
if (opt) {
res = [
...this.value,
- this.returnObject ? opt : opt[this.optionValue]
+ this.returnObject ? opt : getOptionProp(opt, this.optionValue)
];
}
}
@@ -665,7 +675,7 @@ export class CpsSelectComponent
res = this.options;
} else {
this.options.forEach((o) => {
- res.push(o[this.optionValue]);
+ res.push(getOptionProp(o, this.optionValue));
});
}
}
diff --git a/projects/cps-ui-kit/src/lib/components/internal/cps-base-tree-dropdown/cps-base-tree-dropdown.component.ts b/projects/cps-ui-kit/src/lib/components/internal/cps-base-tree-dropdown/cps-base-tree-dropdown.component.ts
index a562f1994..2f1f546d2 100644
--- a/projects/cps-ui-kit/src/lib/components/internal/cps-base-tree-dropdown/cps-base-tree-dropdown.component.ts
+++ b/projects/cps-ui-kit/src/lib/components/internal/cps-base-tree-dropdown/cps-base-tree-dropdown.component.ts
@@ -27,6 +27,7 @@ import { Subscription } from 'rxjs';
import { Tree } from 'primeng/tree';
import { isEqual } from 'lodash-es';
import { IconType, iconSizeType } from '../../cps-icon/cps-icon.component';
+import { getOptionProp, OptionKey } from '../../../utils/internal/option-utils';
import { convertSize } from '../../../utils/internal/size-utils/size-utils';
import { CpsTooltipPosition } from '../../../directives/cps-tooltip/cps-tooltip.directive';
import { CpsMenuComponent } from '../../cps-menu/cps-menu.component';
@@ -107,16 +108,16 @@ export class CpsBaseTreeDropdownComponent
@Input() openOnClear = true;
/**
- * Name of the label field of an option.
+ * Name of the label field of an option, or a function that receives the option and returns the label.
* @group Props
*/
- @Input() optionLabel = 'label';
+ @Input() optionLabel: OptionKey = 'label';
/**
- * Name of the info field of an option, shows the additional information text.
+ * Name of the info field of an option, or a function that receives the option and returns the info text.
* @group Props
*/
- @Input() optionInfo = 'info';
+ @Input() optionInfo: OptionKey = 'info';
/**
* Options for hiding details.
@@ -893,15 +894,15 @@ export class CpsBaseTreeDropdownComponent
private _toInnerOptions(_options: any[]): TreeNode[] {
const mapOption = (
o: any,
- optionLabel: string,
- optionInfo: string,
+ optionLabel: OptionKey,
+ optionInfo: OptionKey,
key: string,
originalOptionsMap: any
) => {
const inner = {
inner: true,
- label: o[optionLabel],
- info: o[optionInfo],
+ label: getOptionProp(o, optionLabel),
+ info: getOptionProp(o, optionInfo),
key,
styleClass: 'key-' + key
} as TreeNode;
diff --git a/projects/cps-ui-kit/src/lib/pipes/internal/check-option-selected/check-option-selected.pipe.ts b/projects/cps-ui-kit/src/lib/pipes/internal/check-option-selected/check-option-selected.pipe.ts
index 4d2c17d8f..c66451e3b 100644
--- a/projects/cps-ui-kit/src/lib/pipes/internal/check-option-selected/check-option-selected.pipe.ts
+++ b/projects/cps-ui-kit/src/lib/pipes/internal/check-option-selected/check-option-selected.pipe.ts
@@ -1,5 +1,6 @@
import { Pipe, PipeTransform } from '@angular/core';
import { isEqual } from 'lodash-es';
+import { getOptionProp, OptionKey } from '../../utils/internal/option-utils';
@Pipe({ standalone: true, name: 'checkOptionSelected' })
export class CheckOptionSelectedPipe implements PipeTransform {
@@ -8,7 +9,7 @@ export class CheckOptionSelectedPipe implements PipeTransform {
value: any,
multiple: boolean,
returnObject: boolean,
- optionValue: string
+ optionValue: OptionKey
): boolean {
function includes(array: any[], val: any): boolean {
return array?.some((item) => isEqual(item, val)) || false;
@@ -17,9 +18,9 @@ export class CheckOptionSelectedPipe implements PipeTransform {
return multiple
? returnObject
? includes(value, option)
- : includes(value, option[optionValue])
+ : includes(value, getOptionProp(option, optionValue))
: returnObject
? isEqual(option, value)
- : isEqual(option[optionValue], value);
+ : isEqual(getOptionProp(option, optionValue), value);
}
}
diff --git a/projects/cps-ui-kit/src/lib/pipes/internal/combine-labels/combine-labels.pipe.ts b/projects/cps-ui-kit/src/lib/pipes/internal/combine-labels/combine-labels.pipe.ts
index 7f3f66a36..f570ac3a1 100644
--- a/projects/cps-ui-kit/src/lib/pipes/internal/combine-labels/combine-labels.pipe.ts
+++ b/projects/cps-ui-kit/src/lib/pipes/internal/combine-labels/combine-labels.pipe.ts
@@ -1,22 +1,25 @@
import { Pipe, PipeTransform } from '@angular/core';
import { isEqual } from 'lodash-es';
+import { getOptionProp, OptionKey } from '../../utils/internal/option-utils';
@Pipe({ standalone: true, name: 'combineLabels' })
export class CombineLabelsPipe implements PipeTransform {
transform(
values: any[],
options: any[],
- valueKey: string,
- labelKey: string,
+ valueKey: OptionKey,
+ labelKey: OptionKey,
returnObject: boolean
): string {
return values
.map((v) => {
if (returnObject) {
- return v[labelKey];
+ return getOptionProp(v, labelKey);
} else {
- const option = options.find((opt) => isEqual(opt[valueKey], v));
- return option ? option[labelKey] : '';
+ const option = options.find((opt) =>
+ isEqual(getOptionProp(opt, valueKey), v)
+ );
+ return option ? getOptionProp(option, labelKey) : '';
}
})
.join(', ');
diff --git a/projects/cps-ui-kit/src/lib/pipes/internal/label-by-value/label-by-value.pipe.ts b/projects/cps-ui-kit/src/lib/pipes/internal/label-by-value/label-by-value.pipe.ts
index a42010055..da1d468a9 100644
--- a/projects/cps-ui-kit/src/lib/pipes/internal/label-by-value/label-by-value.pipe.ts
+++ b/projects/cps-ui-kit/src/lib/pipes/internal/label-by-value/label-by-value.pipe.ts
@@ -1,15 +1,18 @@
import { Pipe, PipeTransform } from '@angular/core';
import { isEqual } from 'lodash-es';
+import { getOptionProp, OptionKey } from '../../utils/internal/option-utils';
@Pipe({ standalone: true, name: 'labelByValue' })
export class LabelByValuePipe implements PipeTransform {
transform(
value: any,
options: any[],
- valueKey: string,
- labelKey: string
+ valueKey: OptionKey,
+ labelKey: OptionKey
): string {
- const option = options.find((opt) => isEqual(opt[valueKey], value));
- return option ? option[labelKey] : '';
+ const option = options.find((opt) =>
+ isEqual(getOptionProp(opt, valueKey), value)
+ );
+ return option ? getOptionProp(option, labelKey) : '';
}
}
diff --git a/projects/cps-ui-kit/src/lib/utils/internal/option-utils.ts b/projects/cps-ui-kit/src/lib/utils/internal/option-utils.ts
new file mode 100644
index 000000000..1dea77722
--- /dev/null
+++ b/projects/cps-ui-kit/src/lib/utils/internal/option-utils.ts
@@ -0,0 +1,6 @@
+export type OptionKey = string | ((option: any) => any);
+
+export function getOptionProp(option: any, key: OptionKey): any {
+ if (typeof key === 'function') return key(option);
+ return option?.[key];
+}
diff --git a/projects/cps-ui-kit/src/public-api.ts b/projects/cps-ui-kit/src/public-api.ts
index e5e6bbda8..ed2bba033 100644
--- a/projects/cps-ui-kit/src/public-api.ts
+++ b/projects/cps-ui-kit/src/public-api.ts
@@ -66,3 +66,4 @@ export * from './lib/services/cps-cron-validation/cps-cron-validation.service';
export * from './lib/services/cps-live-announcer/cps-live-announcer.service';
export * from './lib/utils/colors-utils/colors-utils';
+export { OptionKey } from './lib/utils/internal/option-utils';