@pega/angular-sdk-overrides 0.25.18 → 0.25.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,6 +14,7 @@
14
14
  currencyMask
15
15
  [options]="{
16
16
  prefix: currencySymbol,
17
+ suffix: currencySuffix,
17
18
  thousands: thousandSeparator,
18
19
  decimal: decimalSeparator,
19
20
  align: 'left',
@@ -7,16 +7,27 @@ import { NgxCurrencyDirective, NgxCurrencyInputMode } from 'ngx-currency';
7
7
 
8
8
  import { FieldBase } from '@pega/angular-sdk-components';
9
9
  import { ComponentMapperComponent } from '@pega/angular-sdk-components';
10
- import { handleEvent } from '@pega/angular-sdk-components';
11
- import { getCurrencyCharacters, getCurrencyOptions } from '@pega/angular-sdk-components';
12
- import { format } from '@pega/angular-sdk-components';
10
+ import {
11
+ formatNumberFieldForDisplay,
12
+ getCurrencyInputFormat,
13
+ NumberInputFormat,
14
+ parseFormattedNumber,
15
+ saveNumberOnBlur
16
+ } from '@pega/angular-sdk-components';
13
17
  import { PConnFieldProps } from '@pega/angular-sdk-components';
14
18
 
15
- interface CurrrencyProps extends PConnFieldProps {
19
+ interface CurrrencyProps extends Omit<PConnFieldProps, 'value'> {
16
20
  // If any, enter additional props that only exist on Currency here
21
+ value?: number | string;
17
22
  currencyISOCode?: string;
23
+ alwaysShowISOCode?: boolean;
18
24
  allowDecimals: boolean;
19
25
  formatter?: string;
26
+ currencyDisplay?: 'symbol' | 'code' | 'name';
27
+ negative?: 'minus-sign' | 'parentheses';
28
+ notation?: 'standard' | 'compact';
29
+ currencyDecimalPrecision?: string;
30
+ decimalPrecision?: number | string;
20
31
  }
21
32
 
22
33
  @Component({
@@ -29,14 +40,14 @@ export class CurrencyComponent extends FieldBase {
29
40
  configProps$: CurrrencyProps;
30
41
  override fieldControl = new FormControl<number | null>(null, { updateOn: 'blur' });
31
42
 
32
- currencyOptions: object = {};
33
43
  currencySymbol: string;
44
+ currencySuffix: string;
34
45
  thousandSeparator: string;
35
46
  decimalSeparator: string;
36
47
  decimalPrecision: number | undefined;
37
48
  formattedValue: string;
38
- formatter;
39
49
  inputMode = NgxCurrencyInputMode.Natural;
50
+ private inputFormat: NumberInputFormat;
40
51
 
41
52
  /**
42
53
  * Updates the component when there are changes in the state.
@@ -50,56 +61,38 @@ export class CurrencyComponent extends FieldBase {
50
61
 
51
62
  // Extract and normalize the value property
52
63
  const { value } = this.configProps$;
53
- if (value) {
54
- this.value$ = typeof value === 'string' ? parseFloat(value) : value;
55
- this.fieldControl.setValue(this.value$);
56
- }
64
+ this.value$ = value === undefined || value === null || value === '' ? '' : Number(value);
65
+ this.fieldControl.setValue(this.value$ === '' ? null : this.value$);
57
66
 
58
67
  // update currency properties
59
68
  this.updateCurrencyProperties(this.configProps$);
60
69
  }
61
70
 
62
71
  /**
63
- * Updates the currency properties
64
- *
65
- * @param {Object} configProps - Configuration properties.
66
- * @param {boolean} configProps.allowDecimals - Whether to allow decimal values.
67
- * @param {string} configProps.currencyISOCode - The ISO code of the currency.
68
- * @param {string} configProps.formatter - The formatter type (e.g., 'currency').
72
+ * Updates the input mask and read-only value, matching the Constellation DX Currency component.
69
73
  */
70
- protected updateCurrencyProperties(configProps): void {
71
- const { allowDecimals, currencyISOCode = 'USD', formatter } = configProps;
74
+ protected updateCurrencyProperties(configProps: CurrrencyProps): void {
75
+ const { allowDecimals = true, currencyISOCode = 'USD', alwaysShowISOCode = false } = configProps;
72
76
 
73
- const theSymbols = getCurrencyCharacters(currencyISOCode);
74
- this.currencySymbol = theSymbols.theCurrencySymbol;
75
- this.thousandSeparator = theSymbols.theDigitGroupSeparator;
76
- this.decimalSeparator = theSymbols.theDecimalIndicator;
77
- this.decimalPrecision = allowDecimals ? 2 : 0;
77
+ const inputFormat = getCurrencyInputFormat(
78
+ currencyISOCode,
79
+ this.utils.getBooleanValue(alwaysShowISOCode),
80
+ this.utils.getBooleanValue(allowDecimals)
81
+ );
82
+ this.inputFormat = inputFormat;
83
+ this.currencySymbol = inputFormat.prefix;
84
+ this.currencySuffix = inputFormat.suffix;
85
+ this.thousandSeparator = inputFormat.thousandSeparator;
86
+ this.decimalSeparator = inputFormat.decimalSeparator;
87
+ this.decimalPrecision = inputFormat.precision;
78
88
 
79
89
  if (['DISPLAY_ONLY', 'STACKED_LARGE_VAL'].includes(this.displayMode$)) {
80
- this.formattedValue = format(this.value$, formatter ? formatter.toLowerCase() : 'currency', getCurrencyOptions(currencyISOCode));
90
+ this.formattedValue = formatNumberFieldForDisplay('Currency', this.value$, { ...configProps, currencyISOCode });
81
91
  }
82
92
  }
83
93
 
84
94
  fieldOnBlur(event: any) {
85
- const oldVal = this.value$ ?? '';
86
- const isValueChanged = event.target.value.toString() !== oldVal.toString();
87
-
88
- if (isValueChanged) {
89
- const actionsApi = this.pConn$?.getActionsApi();
90
- const propName = this.pConn$?.getStateProps().value;
91
- let value = event?.target?.value;
92
- value = value?.substring(1);
93
- // replacing thousand separator with empty string as not required in api call
94
- const thousandSep = this.thousandSeparator === '.' ? '\\.' : this.thousandSeparator;
95
- let regExp = new RegExp(String.raw`${thousandSep}`, 'g');
96
- value = value?.replace(regExp, '');
97
- // replacing decimal separator with '.'
98
- if (this.decimalSeparator !== '.') {
99
- regExp = new RegExp(String.raw`${this.decimalSeparator}`, 'g');
100
- value = value.replace(regExp, '.');
101
- }
102
- handleEvent(actionsApi, 'changeNblur', propName, value);
103
- }
95
+ const parsed = parseFormattedNumber(event?.target?.value, this.inputFormat);
96
+ saveNumberOnBlur(this.pConn$, parsed !== '' ? Number(parsed) : '', this.configProps$?.value);
104
97
  }
105
98
  }
@@ -11,8 +11,8 @@
11
11
  matInput
12
12
  currencyMask
13
13
  [options]="{
14
- prefix: currencySymbol,
15
- suffix: suffix,
14
+ prefix: '',
15
+ suffix: '',
16
16
  thousands: thousandSeparator,
17
17
  decimal: decimalSeparator,
18
18
  align: 'left',
@@ -7,17 +7,27 @@ import { NgxCurrencyDirective, NgxCurrencyInputMode } from 'ngx-currency';
7
7
 
8
8
  import { FieldBase } from '@pega/angular-sdk-components';
9
9
  import { ComponentMapperComponent } from '@pega/angular-sdk-components';
10
- import { handleEvent } from '@pega/angular-sdk-components';
11
- import { getCurrencyCharacters, getCurrencyOptions } from '@pega/angular-sdk-components';
12
- import { format } from '@pega/angular-sdk-components';
10
+ import {
11
+ formatNumberFieldForDisplay,
12
+ getNumberInputFormat,
13
+ NumberInputFormat,
14
+ parseDecimalPrecision,
15
+ parseFormattedNumber,
16
+ saveNumberOnBlur
17
+ } from '@pega/angular-sdk-components';
13
18
  import { PConnFieldProps } from '@pega/angular-sdk-components';
14
19
 
15
- interface DecimalProps extends PConnFieldProps {
20
+ interface DecimalProps extends Omit<PConnFieldProps, 'value'> {
16
21
  // If any, enter additional props that only exist on Decimal here
22
+ value?: number | string;
17
23
  currencyISOCode?: string;
18
- decimalPrecision?: number;
19
- showGroupSeparators?: string;
24
+ decimalPrecision?: number | string;
25
+ showGroupSeparators?: boolean | string;
20
26
  formatter?: string;
27
+ currencyDisplay?: 'symbol' | 'code' | 'name';
28
+ negative?: 'minus-sign' | 'parentheses';
29
+ notation?: 'standard' | 'compact';
30
+ currencyDecimalPrecision?: string;
21
31
  }
22
32
 
23
33
  @Component({
@@ -40,12 +50,10 @@ export class DecimalComponent extends FieldBase {
40
50
 
41
51
  decimalSeparator: string;
42
52
  thousandSeparator: string;
43
- currencySymbol = '';
44
53
  decimalPrecision: number | undefined;
45
- formatter;
46
54
  formattedValue: any;
47
55
  inputMode: any = NgxCurrencyInputMode.Natural;
48
- suffix = '';
56
+ private inputFormat: NumberInputFormat;
49
57
 
50
58
  /**
51
59
  * Updates the component when there are changes in the state.
@@ -59,66 +67,34 @@ export class DecimalComponent extends FieldBase {
59
67
 
60
68
  // Extract and normalize the value property
61
69
  const { value } = this.configProps$;
62
- if (value) {
63
- this.value$ = typeof value === 'string' ? parseFloat(value) : value;
64
- this.fieldControl.setValue(this.value$);
65
- }
70
+ this.value$ = value === undefined || value === null || value === '' ? '' : Number(value);
71
+ this.fieldControl.setValue(this.value$ === '' ? null : this.value$);
66
72
 
67
73
  // updates decimal properties
68
74
  this.updateDecimalProperties(this.configProps$);
69
75
  }
70
76
 
71
77
  /**
72
- * Updates decimal properties based on the provided configuration.
73
- *
74
- * @param {Object} configProps - Configuration properties.
75
- * @param {string} configProps.currencyISOCode - ISO code of the currency.
76
- * @param {string} configProps.formatter - Formatter type (e.g., 'decimal', 'currency').
77
- * @param {boolean} configProps.showGroupSeparators - Whether to show group separators.
78
+ * Updates the input mask and read-only value, matching the Constellation DX Decimal component.
78
79
  */
79
- protected updateDecimalProperties(configProps): void {
80
- const { currencyISOCode = '', formatter, showGroupSeparators } = configProps;
81
-
82
- // Extract currency symbols and options
83
- const theSymbols = getCurrencyCharacters(currencyISOCode);
84
- this.decimalSeparator = theSymbols.theDecimalIndicator;
85
- this.thousandSeparator = showGroupSeparators ? theSymbols.theDigitGroupSeparator : '';
86
-
87
- const theCurrencyOptions = getCurrencyOptions(currencyISOCode);
88
- const formatterLower = formatter?.toLowerCase() || 'decimal';
89
- this.formattedValue = format(this.value$, formatterLower, theCurrencyOptions);
90
-
91
- if (this.bReadonly$ && formatter === 'Currency') {
92
- this.currencySymbol = theSymbols.theCurrencySymbol;
80
+ protected updateDecimalProperties(configProps: DecimalProps): void {
81
+ const { decimalPrecision, showGroupSeparators = true } = configProps;
82
+ const numberOfDecimals = parseDecimalPrecision(decimalPrecision, 2);
83
+ const groupSeparators = this.utils.getBooleanValue(showGroupSeparators);
84
+
85
+ this.inputFormat = getNumberInputFormat();
86
+ this.decimalSeparator = this.inputFormat.decimalSeparator;
87
+ this.thousandSeparator = groupSeparators ? this.inputFormat.thousandSeparator : '';
88
+ // ngx-currency needs a fixed precision; Constellation allows any number of decimals when none is configured
89
+ this.decimalPrecision = numberOfDecimals ?? 2;
90
+
91
+ if (['DISPLAY_ONLY', 'STACKED_LARGE_VAL'].includes(this.displayMode$)) {
92
+ this.formattedValue = formatNumberFieldForDisplay('Decimal', this.value$, configProps);
93
93
  }
94
-
95
- if (this.bReadonly$ && formatter === 'Percentage') {
96
- this.suffix = '%';
97
- }
98
-
99
- this.decimalPrecision = this.configProps$?.decimalPrecision ?? 2;
100
94
  }
101
95
 
102
96
  fieldOnBlur(event: any) {
103
- const oldVal = this.value$ ?? '';
104
- const isValueChanged = event.target.value.toString() !== oldVal.toString();
105
-
106
- if (isValueChanged) {
107
- const actionsApi = this.pConn$?.getActionsApi();
108
- const propName = this.pConn$?.getStateProps().value;
109
- let value = event?.target?.value;
110
- // replacing thousand separator with empty string as not required in api call
111
- if (this.configProps$.showGroupSeparators) {
112
- const thousandSep = this.thousandSeparator === '.' ? '\\.' : this.thousandSeparator;
113
- const regExp = new RegExp(String.raw`${thousandSep}`, 'g');
114
- value = value?.replace(regExp, '');
115
- }
116
- // replacing decimal separator with '.'
117
- if (this.decimalSeparator !== '.') {
118
- const regExp = new RegExp(String.raw`${this.decimalSeparator}`, 'g');
119
- value = value.replace(regExp, '.');
120
- }
121
- handleEvent(actionsApi, 'changeNblur', propName, value);
122
- }
97
+ const parsed = parseFormattedNumber(event?.target?.value, this.inputFormat);
98
+ saveNumberOnBlur(this.pConn$, parsed !== '' ? Number(parsed) : '', this.configProps$?.value);
123
99
  }
124
100
  }
@@ -1,5 +1,5 @@
1
1
  <div *ngIf="displayMode$; else noDisplayMode">
2
- <component-mapper *ngIf="bVisible$ !== false" name="FieldValueList" [props]="{ label$, value$, displayMode$ }"></component-mapper>
2
+ <component-mapper *ngIf="bVisible$ !== false" name="FieldValueList" [props]="{ label$, value$: formattedValue, displayMode$ }"></component-mapper>
3
3
  </div>
4
4
  <ng-template #noDisplayMode>
5
5
  <div *ngIf="!bReadonly$ && bHasForm$; else noEdit">
@@ -8,10 +8,19 @@
8
8
  <mat-label>{{ label$ }}</mat-label>
9
9
  <input
10
10
  matInput
11
+ type="text"
12
+ currencyMask
13
+ [options]="{
14
+ prefix: '',
15
+ suffix: '',
16
+ thousands: thousandSeparator,
17
+ decimal: decimalSeparator,
18
+ align: 'left',
19
+ nullable: true,
20
+ precision: 0,
21
+ inputMode: inputMode
22
+ }"
11
23
  [placeholder]="placeholder"
12
- type="number"
13
- step="1"
14
- [value]="value$"
15
24
  [required]="bRequired$"
16
25
  [formControl]="fieldControl"
17
26
  [attr.data-test-id]="testId"
@@ -3,26 +3,48 @@ import { CommonModule } from '@angular/common';
3
3
  import { FormControl, ReactiveFormsModule } from '@angular/forms';
4
4
  import { MatInputModule } from '@angular/material/input';
5
5
  import { MatFormFieldModule } from '@angular/material/form-field';
6
+ import { NgxCurrencyDirective, NgxCurrencyInputMode } from 'ngx-currency';
6
7
 
7
8
  import { FieldBase } from '@pega/angular-sdk-components';
8
9
  import { ComponentMapperComponent } from '@pega/angular-sdk-components';
9
- import { handleEvent } from '@pega/angular-sdk-components';
10
+ import {
11
+ formatNumberFieldForDisplay,
12
+ getNumberInputFormat,
13
+ NumberInputFormat,
14
+ parseFormattedNumber,
15
+ saveNumberOnBlur
16
+ } from '@pega/angular-sdk-components';
10
17
  import { PConnFieldProps } from '@pega/angular-sdk-components';
11
18
 
12
- interface IntegerProps extends PConnFieldProps {
19
+ interface IntegerProps extends Omit<PConnFieldProps, 'value'> {
13
20
  // If any, enter additional props that only exist on Integer here
21
+ value?: number | string;
22
+ showGroupSeparators?: boolean | string;
23
+ formatter?: string;
24
+ decimalPrecision?: number | string;
25
+ currencyISOCode?: string;
26
+ currencyDisplay?: 'symbol' | 'code' | 'name';
27
+ negative?: 'minus-sign' | 'parentheses';
28
+ notation?: 'standard' | 'compact';
29
+ currencyDecimalPrecision?: string;
14
30
  }
15
31
 
16
32
  @Component({
17
33
  selector: 'app-integer',
18
34
  templateUrl: './integer.component.html',
19
35
  styleUrls: ['./integer.component.scss'],
20
- imports: [CommonModule, ReactiveFormsModule, MatFormFieldModule, MatInputModule, forwardRef(() => ComponentMapperComponent)]
36
+ imports: [CommonModule, ReactiveFormsModule, MatFormFieldModule, MatInputModule, NgxCurrencyDirective, forwardRef(() => ComponentMapperComponent)]
21
37
  })
22
38
  export class IntegerComponent extends FieldBase {
23
39
  configProps$: IntegerProps;
24
40
  override fieldControl = new FormControl<number | null>(null, null);
25
41
 
42
+ decimalSeparator: string;
43
+ thousandSeparator: string;
44
+ formattedValue: string;
45
+ inputMode: any = NgxCurrencyInputMode.Natural;
46
+ private inputFormat: NumberInputFormat;
47
+
26
48
  /**
27
49
  * Updates the component when there are changes in the state.
28
50
  */
@@ -35,8 +57,25 @@ export class IntegerComponent extends FieldBase {
35
57
 
36
58
  // Extract and normalize the value property
37
59
  const { value } = this.configProps$;
38
- if (value) {
39
- this.value$ = typeof value === 'string' ? parseInt(value, 10) : value;
60
+ this.value$ = value === undefined || value === null || value === '' ? '' : Number(value);
61
+ this.fieldControl.setValue(this.value$ === '' ? null : this.value$);
62
+
63
+ this.updateIntegerProperties(this.configProps$);
64
+ }
65
+
66
+ /**
67
+ * Updates the input mask and read-only value, matching the Constellation DX Integer component.
68
+ */
69
+ protected updateIntegerProperties(configProps: IntegerProps): void {
70
+ const { showGroupSeparators = true } = configProps;
71
+ const groupSeparators = this.utils.getBooleanValue(showGroupSeparators);
72
+
73
+ this.inputFormat = getNumberInputFormat();
74
+ this.decimalSeparator = this.inputFormat.decimalSeparator;
75
+ this.thousandSeparator = groupSeparators ? this.inputFormat.thousandSeparator : '';
76
+
77
+ if (['DISPLAY_ONLY', 'STACKED_LARGE_VAL'].includes(this.displayMode$)) {
78
+ this.formattedValue = formatNumberFieldForDisplay('Integer', this.value$, configProps);
40
79
  }
41
80
  }
42
81
 
@@ -52,12 +91,7 @@ export class IntegerComponent extends FieldBase {
52
91
  }
53
92
 
54
93
  fieldOnBlur(event: any) {
55
- const oldVal = this.value$ ?? '';
56
- const isValueChanged = event.target.value.toString() !== oldVal.toString();
57
-
58
- if (isValueChanged) {
59
- const value = event?.target?.value;
60
- handleEvent(this.actionsApi, 'changeNblur', this.propName, value);
61
- }
94
+ const parsed = parseFormattedNumber(event?.target?.value, this.inputFormat);
95
+ saveNumberOnBlur(this.pConn$, parsed !== '' ? Number(parsed) : '', this.configProps$?.value);
62
96
  }
63
97
  }
@@ -11,8 +11,8 @@
11
11
  matInput
12
12
  currencyMask
13
13
  [options]="{
14
- prefix: '',
15
- suffix: '%',
14
+ prefix: prefix,
15
+ suffix: suffix,
16
16
  thousands: thousandSeparator,
17
17
  decimal: decimalSeparator,
18
18
  align: 'left',
@@ -7,16 +7,24 @@ import { NgxCurrencyDirective, NgxCurrencyInputMode } from 'ngx-currency';
7
7
 
8
8
  import { FieldBase } from '@pega/angular-sdk-components';
9
9
  import { ComponentMapperComponent } from '@pega/angular-sdk-components';
10
- import { handleEvent } from '@pega/angular-sdk-components';
11
- import { getCurrencyCharacters } from '@pega/angular-sdk-components';
12
- import { format } from '@pega/angular-sdk-components';
10
+ import {
11
+ decimalsToPercentage,
12
+ formatNumberFieldForDisplay,
13
+ getNumberInputFormat,
14
+ NumberInputFormat,
15
+ parseDecimalPrecision,
16
+ parseFormattedNumber,
17
+ percentageToDecimals,
18
+ saveNumberOnBlur
19
+ } from '@pega/angular-sdk-components';
13
20
  import { PConnFieldProps } from '@pega/angular-sdk-components';
14
21
 
15
22
  interface PercentageProps extends Omit<PConnFieldProps, 'value'> {
16
- value?: number;
17
- showGroupSeparators?: string;
18
- decimalPrecision?: number;
23
+ value?: number | string;
24
+ showGroupSeparators?: boolean | string;
25
+ decimalPrecision?: number | string;
19
26
  currencyISOCode?: string;
27
+ storePercentageAsDecimal?: boolean | string;
20
28
  // If any, enter additional props that only exist on Percentage here
21
29
  }
22
30
 
@@ -30,11 +38,16 @@ export class PercentageComponent extends FieldBase {
30
38
  configProps$: PercentageProps;
31
39
  override fieldControl = new FormControl<number | null>(null, null);
32
40
 
41
+ prefix: string;
42
+ suffix: string;
33
43
  decimalSeparator: string;
34
44
  thousandSeparator: string;
35
45
  inputMode: any = NgxCurrencyInputMode.Natural;
36
46
  decimalPrecision: number | undefined;
37
47
  formattedValue: string;
48
+ private inputFormat: NumberInputFormat;
49
+ private numberOfDecimals: number | undefined;
50
+ private storeAsDecimal = false;
38
51
 
39
52
  /**
40
53
  * Updates the component when there are changes in the state.
@@ -46,34 +59,39 @@ export class PercentageComponent extends FieldBase {
46
59
  // Update component common properties
47
60
  this.updateComponentCommonProperties(this.configProps$);
48
61
 
49
- // Set component specific properties
50
- const { value } = this.configProps$;
51
- if (value) {
52
- this.value$ = value;
53
- this.fieldControl.setValue(value);
62
+ const { value, decimalPrecision, storePercentageAsDecimal } = this.configProps$;
63
+ this.numberOfDecimals = parseDecimalPrecision(decimalPrecision, 2);
64
+ this.storeAsDecimal = this.utils.getBooleanValue(storePercentageAsDecimal);
65
+
66
+ // The stored value may be a fraction (0.25); the field always shows/edits the percentage (25)
67
+ if (value === undefined || value === null || value === '') {
68
+ this.value$ = '';
69
+ } else {
70
+ this.value$ = this.storeAsDecimal && Number(value) ? decimalsToPercentage(Number(value), this.numberOfDecimals) : Number(value);
54
71
  }
72
+ this.fieldControl.setValue(this.value$ === '' ? null : this.value$);
55
73
 
56
74
  // update percentage properties
57
75
  this.updatePercentageProperties(this.configProps$);
58
76
  }
59
77
 
60
78
  /**
61
- * Updates the percentage properties
62
- *
63
- * @param {Object} configProps - Configuration properties.
64
- * @param {boolean} configProps.showGroupSeparators - Whether to show group separators.
65
- * @param {number} configProps.decimalPrecision - The number of decimal places to display.
79
+ * Updates the input mask and read-only value, matching the Constellation DX Percentage component.
66
80
  */
67
- updatePercentageProperties(configProps): void {
68
- const { showGroupSeparators, decimalPrecision } = configProps;
81
+ updatePercentageProperties(configProps: PercentageProps): void {
82
+ const { showGroupSeparators = false } = configProps;
83
+ const groupSeparators = this.utils.getBooleanValue(showGroupSeparators);
69
84
 
70
- const theSymbols = getCurrencyCharacters('');
71
- this.decimalSeparator = theSymbols.theDecimalIndicator;
72
- this.thousandSeparator = showGroupSeparators ? theSymbols.theDigitGroupSeparator : '';
73
- this.decimalPrecision = decimalPrecision ?? 2;
85
+ this.inputFormat = getNumberInputFormat('percent');
86
+ this.prefix = this.inputFormat.prefix;
87
+ this.suffix = this.inputFormat.suffix;
88
+ this.decimalSeparator = this.inputFormat.decimalSeparator;
89
+ this.thousandSeparator = groupSeparators ? this.inputFormat.thousandSeparator : '';
90
+ // ngx-currency needs a fixed precision; Constellation allows any number of decimals when none is configured
91
+ this.decimalPrecision = this.numberOfDecimals ?? 2;
74
92
 
75
93
  if (['DISPLAY_ONLY', 'STACKED_LARGE_VAL'].includes(this.displayMode$)) {
76
- this.formattedValue = this.value$ ? format(this.value$, 'percentage') : '';
94
+ this.formattedValue = formatNumberFieldForDisplay('Percentage', this.value$, configProps);
77
95
  }
78
96
  }
79
97
 
@@ -89,24 +107,11 @@ export class PercentageComponent extends FieldBase {
89
107
  }
90
108
 
91
109
  fieldOnBlur(event: any) {
92
- const oldVal = this.value$ ?? '';
93
- const isValueChanged = event.target.value.toString() !== oldVal.toString();
94
-
95
- if (isValueChanged) {
96
- let value = event?.target?.value;
97
- value = value ? value.replace(/%/g, '') : '';
98
- // replacing thousand separator with empty string as not required in api call
99
- if (this.configProps$.showGroupSeparators) {
100
- const thousandSep = this.thousandSeparator === '.' ? '\\.' : this.thousandSeparator;
101
- const regExp = new RegExp(String.raw`${thousandSep}`, 'g');
102
- value = value?.replace(regExp, '');
103
- }
104
- // replacing decimal separator with '.'
105
- if (this.decimalSeparator !== '.') {
106
- const regExp = new RegExp(String.raw`${this.decimalSeparator}`, 'g');
107
- value = value.replace(regExp, '.');
108
- }
109
- handleEvent(this.actionsApi, 'changeNblur', this.propName, value);
110
+ const parsed = parseFormattedNumber(event?.target?.value, this.inputFormat);
111
+ let newValue: number | '' = parsed !== '' ? Number(parsed) : '';
112
+ if (this.storeAsDecimal && newValue !== '') {
113
+ newValue = percentageToDecimals(newValue, this.numberOfDecimals);
110
114
  }
115
+ saveNumberOnBlur(this.pConn$, newValue, this.configProps$?.value);
111
116
  }
112
117
  }
@@ -110,7 +110,6 @@ export class NavbarComponent implements OnInit, OnDestroy {
110
110
 
111
111
  // making a copy, so can add info
112
112
  this.navPages$ = JSON.parse(JSON.stringify(this.pages$));
113
- // @ts-ignore
114
113
  const localeReference = PCore.getLocaleUtils().getPortalLocaleReference() || this.pConn$.getValue('.pyLocaleReference');
115
114
  this.navPages$.forEach(page => {
116
115
  const destinationObject: any = {};
@@ -88,8 +88,7 @@ export class ReferenceComponent implements OnInit, OnDestroy, OnChanges {
88
88
  }
89
89
  };
90
90
 
91
- // @ts-expect-error - createComponent expects string but null is passed for unused parameters (matches React SDK pattern)
92
- const viewComponent: any = pConnect.createComponent(viewObject, null, null, {
91
+ const viewComponent: any = pConnect.createComponent(viewObject, '', 0, {
93
92
  pageReference: context && context.startsWith('@CLASS') ? '' : context
94
93
  });
95
94
 
@@ -71,7 +71,6 @@ export class AdvancedSearchComponent implements OnInit, OnChanges {
71
71
  const [firstChildMeta] = rawViewMetadata.children;
72
72
 
73
73
  const localizedVal = PCore.getLocaleUtils().getLocaleValue;
74
- // @ts-ignore
75
74
  const cache = PCore.getNavigationUtils().getComponentCache(searchSelectCacheKey) ?? {};
76
75
 
77
76
  this.editableFieldComp = firstChildPConnect().createComponent({
@@ -210,8 +210,7 @@ export class SearchGroupsComponent implements OnInit, OnDestroy, OnChanges {
210
210
  isValidInput(formValues)
211
211
  ) {
212
212
  if (this.isValidatorField) {
213
- // @ts-ignore
214
- PCore.getMessageManager().clearContextMessages({ context: transientItemID });
213
+ PCore.getMessageManager().clearContextMessages({ context: this.transientItemID });
215
214
  }
216
215
 
217
216
  this.previousFormValues = formValues;
@@ -220,13 +219,13 @@ export class SearchGroupsComponent implements OnInit, OnDestroy, OnChanges {
220
219
  PCore.getPubSubUtils().publish(PCore.getEvents().getTransientEvent().UPDATE_PROMOTED_FILTERS, {
221
220
  payload: formValues,
222
221
  showRecords: true,
223
- viewName: this.getPConnect.getCurrentView()
222
+ viewName: this.getPConnect().getCurrentView()
224
223
  });
225
224
  }
226
225
 
227
226
  this.state.activeGroupId = this.activeGroupId;
228
227
  this.state.searchFields = changes;
229
- this.state.selectedCategory = this.getPConnect.getCurrentView();
228
+ this.state.selectedCategory = this.getPConnect().getCurrentView();
230
229
  const options = componentCachePersistUtils.getComponentStateOptions(this.getPConnect);
231
230
  componentCachePersistUtils.setComponentCache({
232
231
  cacheKey: this.searchSelectCacheKey,
@@ -89,7 +89,6 @@ export class AppShellComponent implements OnInit, OnDestroy {
89
89
  PCore.getEnvironmentInfo().setEnvironmentInfo({ ...PCore.getEnvironmentInfo().environmentInfoObject, pyPortalTemplate: 'wss' } as any);
90
90
  }
91
91
 
92
- // @ts-ignore - Property 'pyCaseTypesAvailableToCreateDP' does not exist on type pxApplication
93
92
  const caseTypesAvailableToCreateDP = PCore.getEnvironmentInfo().environmentInfoObject?.pxApplication?.pyCaseTypesAvailableToCreateDP;
94
93
  if (caseTypesAvailableToCreateDP) {
95
94
  const portalID = this.pConn$.getValue('.pyOwner');
@@ -398,7 +398,6 @@ export class DataReferenceComponent implements OnInit, OnDestroy {
398
398
  if (['Dropdown', 'Checkbox', 'RadioButtons'].includes(type) && !config.deferDatasource && config.datasource) {
399
399
  const isCardVariant = config.variant === 'card';
400
400
  const hasParameters = this.rawViewMetadata.config?.parameters;
401
- // @ts-ignore
402
401
  const isDeferDataPageCallEnabled = isCardVariant && hasParameters && !this.firstChildPConnect()?.getSharedDataPageForReferenceList();
403
402
 
404
403
  const useDropDownDataSource = (isCardVariant && (this.dropDownDataSource || isDeferDataPageCallEnabled)) || (!isCardVariant && hasParameters);
@@ -127,7 +127,6 @@ export function getData(deferLoadedTabs, tabCountSources, currentTabId, data) {
127
127
  });
128
128
  } else if (calculatedFieldsWithoutValue.length) {
129
129
  PCore.getViewRuleApi()
130
- // @ts-ignore
131
130
  .getCalculatedFields(
132
131
  pConn.getCaseInfo().getKey(),
133
132
  pConn.getCurrentView(),
@@ -346,7 +346,6 @@ export class ListViewComponent implements OnInit, OnDestroy {
346
346
  }
347
347
 
348
348
  getFieldsMetadata(refList) {
349
- // @ts-ignore - 3rd parameter "associationFilter" should be optional for getDataViewMetadata method
350
349
  return PCore.getAnalyticsUtils().getDataViewMetadata(refList, this.showDynamicFields);
351
350
  }
352
351
 
@@ -217,7 +217,7 @@ export const updateFieldLabels = (fields, configFields, primaryFieldsViewIndex,
217
217
  let label = configFields[i].config?.label;
218
218
  if (isFLProperty(label)) {
219
219
  label = getFieldLabel(configFields[i].config);
220
- } else if (label.startsWith('@')) {
220
+ } else if (label?.startsWith('@')) {
221
221
  label = label.substring(3);
222
222
  }
223
223
  if (pConnect) {
@@ -32,7 +32,6 @@ export const evaluateAllowRowAction = (allowRowDelete, rowData) => {
32
32
  if (allowRowDelete === undefined || allowRowDelete === true) return true;
33
33
  if (allowRowDelete.startsWith?.('@E ')) {
34
34
  const expression = allowRowDelete.replace('@E ', '');
35
- // @ts-ignore - Expected 3 arguments, but got 2
36
35
  return PCore.getExpressionEngine().evaluate(expression, rowData);
37
36
  }
38
37
  return false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pega/angular-sdk-overrides",
3
- "version": "0.25.18",
3
+ "version": "0.25.20",
4
4
  "description": "Angular SDK - Code for overriding components",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"