WEB-643 fix(clients): add takeUntil pattern to prevent memory leaks in client-general-step component (#3065)

improve
This commit is contained in:
Shubham Kumar
2026-01-31 13:54:14 -06:00
committed by GitHub
parent c1cacdfb6d
commit 163ad131d7
@@ -7,7 +7,7 @@
*/ */
/** Angular Imports */ /** Angular Imports */
import { Component, OnInit, Input, Output, EventEmitter, inject } from '@angular/core'; import { Component, OnInit, OnDestroy, Input, Output, EventEmitter, inject } from '@angular/core';
import { import {
UntypedFormBuilder, UntypedFormBuilder,
UntypedFormGroup, UntypedFormGroup,
@@ -15,6 +15,8 @@ import {
UntypedFormControl, UntypedFormControl,
ReactiveFormsModule ReactiveFormsModule
} from '@angular/forms'; } from '@angular/forms';
import { Subject } from 'rxjs';
import { filter, switchMap, takeUntil } from 'rxjs/operators';
import { ClientsService } from 'app/clients/clients.service'; import { ClientsService } from 'app/clients/clients.service';
import { Dates } from 'app/core/utils/dates'; import { Dates } from 'app/core/utils/dates';
@@ -44,12 +46,15 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
MatStepperNext MatStepperNext
] ]
}) })
export class ClientGeneralStepComponent implements OnInit { export class ClientGeneralStepComponent implements OnInit, OnDestroy {
private formBuilder = inject(UntypedFormBuilder); private formBuilder = inject(UntypedFormBuilder);
private dateUtils = inject(Dates); private dateUtils = inject(Dates);
private settingsService = inject(SettingsService); private settingsService = inject(SettingsService);
private clientService = inject(ClientsService); private clientService = inject(ClientsService);
/** Subject to trigger unsubscription on destroy */
private destroy$ = new Subject<void>();
@Output() legalFormChangeEvent = new EventEmitter<{ legalForm: number }>(); @Output() legalFormChangeEvent = new EventEmitter<{ legalForm: number }>();
/** Minimum date allowed. */ /** Minimum date allowed. */
@@ -151,72 +156,91 @@ export class ClientGeneralStepComponent implements OnInit {
* Adds controls conditionally. * Adds controls conditionally.
*/ */
buildDependencies() { buildDependencies() {
this.createClientForm.get('legalFormId').valueChanges.subscribe((legalFormId: number) => { this.createClientForm
this.legalFormChangeEvent.emit({ legalForm: legalFormId }); .get('legalFormId')
if (legalFormId === 1) { .valueChanges.pipe(takeUntil(this.destroy$))
this.createClientForm.removeControl('fullname'); .subscribe((legalFormId: number) => {
this.createClientForm.removeControl('clientNonPersonDetails'); this.legalFormChangeEvent.emit({ legalForm: legalFormId });
this.createClientForm.addControl( if (legalFormId === 1) {
'firstname', this.createClientForm.removeControl('fullname');
new UntypedFormControl('', [ this.createClientForm.removeControl('clientNonPersonDetails');
Validators.required, this.createClientForm.addControl(
Validators.pattern('(^[A-z]).*') 'firstname',
]) new UntypedFormControl('', [
); Validators.required,
this.createClientForm.addControl('middlename', new UntypedFormControl('', Validators.pattern('(^[A-z]).*'))); Validators.pattern('(^[A-z]).*')
this.createClientForm.addControl( ])
'lastname', );
new UntypedFormControl('', [ this.createClientForm.addControl('middlename', new UntypedFormControl('', Validators.pattern('(^[A-z]).*')));
Validators.required, this.createClientForm.addControl(
Validators.pattern('(^[A-z]).*') 'lastname',
]) new UntypedFormControl('', [
); Validators.required,
} else { Validators.pattern('(^[A-z]).*')
this.createClientForm.removeControl('firstname'); ])
this.createClientForm.removeControl('middlename'); );
this.createClientForm.removeControl('lastname'); } else {
this.createClientForm.addControl( this.createClientForm.removeControl('firstname');
'fullname', this.createClientForm.removeControl('middlename');
new UntypedFormControl('', [ this.createClientForm.removeControl('lastname');
Validators.required, this.createClientForm.addControl(
Validators.pattern('(^[A-z]).*') 'fullname',
]) new UntypedFormControl('', [
); Validators.required,
this.createClientForm.addControl( Validators.pattern('(^[A-z]).*')
'clientNonPersonDetails', ])
this.formBuilder.group({ );
constitutionId: [ this.createClientForm.addControl(
'', 'clientNonPersonDetails',
Validators.required this.formBuilder.group({
], constitutionId: [
incorpValidityTillDate: [''], '',
incorpNumber: [''], Validators.required
mainBusinessLineId: [''], ],
remarks: [''] incorpValidityTillDate: [''],
}) incorpNumber: [''],
); mainBusinessLineId: [''],
} remarks: ['']
}); })
);
}
});
this.createClientForm.get('legalFormId').patchValue(1); this.createClientForm.get('legalFormId').patchValue(1);
this.createClientForm.get('active').valueChanges.subscribe((active: boolean) => { this.createClientForm
if (active) { .get('active')
this.createClientForm.addControl('activationDate', new UntypedFormControl('', Validators.required)); .valueChanges.pipe(takeUntil(this.destroy$))
} else { .subscribe((active: boolean) => {
this.createClientForm.removeControl('activationDate'); if (active) {
} this.createClientForm.addControl('activationDate', new UntypedFormControl('', Validators.required));
}); } else {
this.createClientForm.get('addSavings').valueChanges.subscribe((active: boolean) => { this.createClientForm.removeControl('activationDate');
if (active) { }
this.createClientForm.addControl('savingsProductId', new UntypedFormControl('', Validators.required)); });
} else { this.createClientForm
this.createClientForm.removeControl('savingsProductId'); .get('addSavings')
} .valueChanges.pipe(takeUntil(this.destroy$))
}); .subscribe((active: boolean) => {
this.createClientForm.get('officeId').valueChanges.subscribe((officeId: number) => { if (active) {
this.clientService.getClientWithOfficeTemplate(officeId).subscribe((clientTemplate: any) => { this.createClientForm.addControl('savingsProductId', new UntypedFormControl('', Validators.required));
} else {
this.createClientForm.removeControl('savingsProductId');
}
});
this.createClientForm
.get('officeId')
.valueChanges.pipe(
filter((officeId: number) => !!officeId),
switchMap((officeId: number) => this.clientService.getClientWithOfficeTemplate(officeId)),
takeUntil(this.destroy$)
)
.subscribe((clientTemplate: any) => {
this.staffOptions = clientTemplate.staffOptions; this.staffOptions = clientTemplate.staffOptions;
}); });
}); }
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
} }
getDateLabel(legalFormId: number, values: string[]): string { getDateLabel(legalFormId: number, values: string[]): string {