Skip to content

Commit 7a6d75d

Browse files
authored
refactor: base component for field components added (#332)
* refactor: base component for field components added * constellationjs 25.1.0 package installed
1 parent f866818 commit 7a6d75d

File tree

28 files changed

+657
-2840
lines changed

28 files changed

+657
-2840
lines changed

package-lock.json

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
"@angular/platform-browser-dynamic": "^19.2.14",
7070
"@angular/router": "^19.2.14",
7171
"@danielmoncada/angular-datetime-picker": "^19.0.0",
72-
"@pega/auth": "~0.2.31",
72+
"@pega/auth": "~0.2.34",
7373
"@tinymce/tinymce-angular": "^8.0.1",
7474
"core-js": "^3.39.0",
7575
"dayjs": "^1.11.13",
@@ -94,7 +94,7 @@
9494
"@angular/compiler-cli": "^19.2.14",
9595
"@angular/language-service": "^19.2.14",
9696
"@pega/configs": "^0.16.3",
97-
"@pega/constellationjs": "^0.25.1",
97+
"@pega/constellationjs": "~25.1.0",
9898
"@pega/pcore-pconnect-typedefs": "~4.1.0",
9999
"@playwright/test": "^1.54.2",
100100
"@types/jasmine": "~5.1.4",
Lines changed: 26 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
import { Component, OnInit, Input, ChangeDetectorRef, forwardRef, OnDestroy, Output, EventEmitter } from '@angular/core';
1+
import { Component, EventEmitter, OnInit, Output, forwardRef, inject } from '@angular/core';
22
import { CommonModule } from '@angular/common';
3-
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
3+
import { ReactiveFormsModule } from '@angular/forms';
44
import { MatOptionModule } from '@angular/material/core';
55
import { MatAutocompleteModule } from '@angular/material/autocomplete';
66
import { MatInputModule } from '@angular/material/input';
77
import { MatFormFieldModule } from '@angular/material/form-field';
8-
import { interval, Observable } from 'rxjs';
8+
import { Observable } from 'rxjs';
99
import { map, startWith } from 'rxjs/operators';
10-
import { AngularPConnectData, AngularPConnectService } from '../../../_bridge/angular-pconnect';
11-
import { Utils } from '../../../_helpers/utils';
10+
11+
import { FieldBase } from '../field.base';
1212
import { ComponentMapperComponent } from '../../../_bridge/component-mapper/component-mapper.component';
1313
import { DatapageService } from '../../../_services/datapage.service';
1414
import { handleEvent } from '../../../_helpers/event-util';
@@ -44,67 +44,23 @@ interface AutoCompleteProps extends PConnFieldProps {
4444
forwardRef(() => ComponentMapperComponent)
4545
]
4646
})
47-
export class AutoCompleteComponent implements OnInit, OnDestroy {
48-
@Input() pConn$: typeof PConnect;
49-
@Input() formGroup$: FormGroup;
47+
export class AutoCompleteComponent extends FieldBase implements OnInit {
48+
protected dataPageService = inject(DatapageService);
49+
5050
@Output() onRecordChange: EventEmitter<any> = new EventEmitter();
5151

52-
// Used with AngularPConnect
53-
angularPConnectData: AngularPConnectData = {};
5452
configProps$: AutoCompleteProps;
5553

56-
label$ = '';
57-
value$ = '';
58-
bRequired$ = false;
59-
bReadonly$ = false;
60-
bDisabled$ = false;
61-
bVisible$ = true;
62-
displayMode$?: string = '';
63-
controlName$: string;
64-
bHasForm$ = true;
6554
options$: any[];
66-
componentReference = '';
67-
testId: string;
6855
listType: string;
6956
columns = [];
70-
helperText: string;
71-
placeholder: string;
72-
73-
fieldControl = new FormControl('', null);
7457
parameters: {};
75-
hideLabel: boolean;
7658
filteredOptions: Observable<any[]>;
7759
filterValue = '';
78-
actionsApi: object;
79-
propName: string;
80-
81-
constructor(
82-
private angularPConnect: AngularPConnectService,
83-
private cdRef: ChangeDetectorRef,
84-
private utils: Utils,
85-
private dataPageService: DatapageService
86-
) {}
87-
88-
async ngOnInit(): Promise<void> {
89-
// First thing in initialization is registering and subscribing to the AngularPConnect service
90-
this.angularPConnectData = this.angularPConnect.registerAndSubscribeComponent(this, this.onStateChange);
91-
this.controlName$ = this.angularPConnect.getComponentID(this);
92-
93-
// Then, continue on with other initialization
9460

95-
// call updateSelf when initializing
96-
// this.updateSelf();
97-
await this.checkAndUpdate();
98-
99-
if (this.formGroup$) {
100-
// add control to formGroup
101-
this.formGroup$.addControl(this.controlName$, this.fieldControl);
102-
this.fieldControl.setValue(this.value$);
103-
this.bHasForm$ = true;
104-
} else {
105-
this.bReadonly$ = true;
106-
this.bHasForm$ = false;
107-
}
61+
// Override ngOnInit method
62+
override async ngOnInit(): Promise<void> {
63+
super.ngOnInit();
10864

10965
this.filteredOptions = this.fieldControl.valueChanges.pipe(
11066
startWith(''),
@@ -119,89 +75,40 @@ export class AutoCompleteComponent implements OnInit, OnDestroy {
11975
this.fieldControl.setValue(this.value$);
12076
}
12177

122-
ngOnDestroy(): void {
123-
if (this.formGroup$) {
124-
this.formGroup$.removeControl(this.controlName$);
125-
}
126-
127-
if (this.angularPConnectData.unsubscribeFn) {
128-
this.angularPConnectData.unsubscribeFn();
129-
}
130-
}
131-
13278
private _filter(value: string): string[] {
13379
const filterVal = (value || this.filterValue).toLowerCase();
13480
return this.options$?.filter(option => option.value?.toLowerCase().includes(filterVal));
13581
}
13682

137-
// Callback passed when subscribing to store change
138-
async onStateChange() {
139-
await this.checkAndUpdate();
140-
}
141-
142-
async checkAndUpdate() {
143-
// Should always check the bridge to see if the component should
144-
// update itself (re-render)
145-
const bUpdateSelf = this.angularPConnect.shouldComponentUpdate(this);
146-
147-
// ONLY call updateSelf when the component should update
148-
if (bUpdateSelf) {
149-
await this.updateSelf();
150-
}
151-
}
83+
/**
84+
* Updates the component when there are changes in the state.
85+
*/
86+
override async updateSelf(): Promise<void> {
87+
// Resolve configuration properties
88+
this.configProps$ = this.pConn$.resolveConfigProps(this.pConn$.getConfigProps()) as AutoCompleteProps;
15289

153-
// updateSelf
154-
async updateSelf(): Promise<void> {
155-
// starting very simple...
90+
// Update component common properties
91+
this.updateComponentCommonProperties(this.configProps$);
15692

157-
// moved this from ngOnInit() and call this from there instead...
158-
this.configProps$ = this.pConn$.resolveConfigProps(this.pConn$.getConfigProps()) as AutoCompleteProps;
93+
// Set component specific properties
94+
const { value, listType, parameters } = this.configProps$;
15995

160-
if (this.configProps$.value != undefined) {
161-
const index = this.options$?.findIndex(element => element.key === this.configProps$.value);
162-
this.value$ = index > -1 ? this.options$[index].value : this.configProps$.value;
96+
if (value != undefined) {
97+
const index = this.options$?.findIndex(element => element.key === value);
98+
this.value$ = index > -1 ? this.options$[index].value : value;
16399
this.fieldControl.setValue(this.value$);
164100
}
165101

166-
this.setPropertyValuesFromProps();
167-
168-
this.actionsApi = this.pConn$.getActionsApi();
169-
this.propName = this.pConn$.getStateProps().value;
102+
this.listType = listType;
103+
this.parameters = parameters;
170104

171105
const context = this.pConn$.getContextName();
172106
const { columns, datasource } = this.generateColumnsAndDataSource();
173107

174108
if (columns) {
175109
this.columns = this.preProcessColumns(columns);
176110
}
177-
// timeout and detectChanges to avoid ExpressionChangedAfterItHasBeenCheckedError
178-
setTimeout(() => {
179-
if (this.configProps$.required != null) {
180-
this.bRequired$ = this.utils.getBooleanValue(this.configProps$.required);
181-
}
182-
this.cdRef.detectChanges();
183-
});
184-
185-
if (this.configProps$.visibility != null) {
186-
this.bVisible$ = this.utils.getBooleanValue(this.configProps$.visibility);
187-
}
188-
189-
// disabled
190-
if (this.configProps$.disabled != undefined) {
191-
this.bDisabled$ = this.utils.getBooleanValue(this.configProps$.disabled);
192-
}
193111

194-
if (this.bDisabled$) {
195-
this.fieldControl.disable();
196-
} else {
197-
this.fieldControl.enable();
198-
}
199-
200-
if (this.configProps$.readOnly != null) {
201-
this.bReadonly$ = this.utils.getBooleanValue(this.configProps$.readOnly);
202-
}
203-
204-
this.componentReference = this.pConn$.getStateProps().value;
205112
if (this.listType === 'associated') {
206113
const optionsList = this.utils.getOptionList(this.configProps$, this.pConn$.getDataObject('')); // 1st arg empty string until typedef marked correctly
207114
this.setOptions(optionsList);
@@ -211,27 +118,6 @@ export class AutoCompleteComponent implements OnInit, OnDestroy {
211118
const results = await this.dataPageService.getDataPageData(datasource, this.parameters, context);
212119
this.fillOptions(results);
213120
}
214-
215-
// trigger display of error message with field control
216-
if (this.angularPConnectData.validateMessage != null && this.angularPConnectData.validateMessage != '') {
217-
const timer = interval(100).subscribe(() => {
218-
this.fieldControl.setErrors({ message: true });
219-
this.fieldControl.markAsTouched();
220-
221-
timer.unsubscribe();
222-
});
223-
}
224-
}
225-
226-
setPropertyValuesFromProps() {
227-
this.testId = this.configProps$.testId;
228-
this.label$ = this.configProps$.label;
229-
this.placeholder = this.configProps$.placeholder || '';
230-
this.displayMode$ = this.configProps$.displayMode;
231-
this.listType = this.configProps$.listType;
232-
this.hideLabel = this.configProps$.hideLabel;
233-
this.helperText = this.configProps$.helperText;
234-
this.parameters = this.configProps$?.parameters;
235121
}
236122

237123
generateColumnsAndDataSource() {
@@ -313,10 +199,6 @@ export class AutoCompleteComponent implements OnInit, OnDestroy {
313199
}
314200

315201
fieldOnChange(event: Event) {
316-
// this works - this.pConn$.setValue( this.componentReference, `property: ${this.componentReference}`);
317-
// this works - this.pConn$.setValue( this.componentReference, this.fieldControl.value);
318-
// PConnect wants to use changeHandler for onChange
319-
// this.angularPConnect.changeHandler( this, event);
320202
const value = (event.target as HTMLInputElement).value;
321203
this.filterValue = value;
322204
handleEvent(this.actionsApi, 'change', this.propName, value);
@@ -337,21 +219,4 @@ export class AutoCompleteComponent implements OnInit, OnDestroy {
337219
this.onRecordChange.emit(value);
338220
}
339221
}
340-
341-
getErrorMessage() {
342-
let errMessage = '';
343-
344-
// look for validation messages for json, pre-defined or just an error pushed from workitem (400)
345-
if (this.fieldControl.hasError('message')) {
346-
errMessage = this.angularPConnectData.validateMessage ?? '';
347-
return errMessage;
348-
}
349-
if (this.fieldControl.hasError('required')) {
350-
errMessage = 'You must enter a value';
351-
} else if (this.fieldControl.errors) {
352-
errMessage = this.fieldControl.errors.toString();
353-
}
354-
355-
return errMessage;
356-
}
357222
}

0 commit comments

Comments
 (0)