From 620ffae55ce5bffcf1164fb124128825ae112c5b Mon Sep 17 00:00:00 2001 From: Lorenz Hilpert Date: Wed, 9 Apr 2025 07:30:44 +0000 Subject: [PATCH] =?UTF-8?q?Merged=20PR=201829:=20Kundendaten=20//=20B2B=20?= =?UTF-8?q?-=20nach=20"Bearbeiten"=20speichern=20nicht=20m=C3=B6glich?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bugfix: Show error when control has error Rename validator requiredIfControlIsSet to requireGenderWhenNameIsSet Update logic for requireGenderWhenNameIsSet Added JSDoc for Documentation UiFormControlComponent Subscribing to ngControl.statusChanges and ngControl.valueChanges independendly and call cdr.markForCheck when emitted Related work items: #4996 --- .../customer-data-edit.component.ts | 5 +-- .../validators/gender-b2b-validator.ts | 45 ++++++++++++++----- .../form-control/ui-form-control.component.ts | 16 ++++--- 3 files changed, 45 insertions(+), 21 deletions(-) diff --git a/apps/isa-app/src/page/customer/customer-search/edit-main-view/customer-data-edit.component.ts b/apps/isa-app/src/page/customer/customer-search/edit-main-view/customer-data-edit.component.ts index 15199adce..b6f6b6ffa 100644 --- a/apps/isa-app/src/page/customer/customer-search/edit-main-view/customer-data-edit.component.ts +++ b/apps/isa-app/src/page/customer/customer-search/edit-main-view/customer-data-edit.component.ts @@ -15,7 +15,7 @@ import { UiValidators } from '@ui/validators'; import { Observable, combineLatest } from 'rxjs'; import { first, map, switchMap } from 'rxjs/operators'; import { validateEmail } from '../../validators/email-validator'; -import { requiredIfControlIsSet } from '../../validators/gender-b2b-validator'; +import { requireGenderWhenNameIsSet } from '../../validators/gender-b2b-validator'; import { camelCase } from 'lodash'; import { CustomerSearchStore } from '../store'; import { CustomerSearchNavigation, NavigationRoute } from '@shared/services/navigation'; @@ -125,7 +125,6 @@ export abstract class CustomerDataEditComponent implements OnInit { const customerType = await this.customerType$.pipe(first()).toPromise(); const customerFeatures = await this.customerFeatures$.pipe(first()).toPromise(); const isB2b = customerType === 'b2b'; - const isBranch = customerType === 'store'; const isWebshop = customerType === 'webshop'; const isCard = customerFeatures.find((feature) => feature.key === 'p4muser'); @@ -169,7 +168,7 @@ export abstract class CustomerDataEditComponent implements OnInit { }, { // #1461 KKM/ISA: Anrede als Pflichtfeld - validators: [requiredIfControlIsSet('gender', 'lastName')], + validators: [requireGenderWhenNameIsSet], }, ); diff --git a/apps/isa-app/src/page/customer/validators/gender-b2b-validator.ts b/apps/isa-app/src/page/customer/validators/gender-b2b-validator.ts index 990be3e6b..4e5fc2b88 100644 --- a/apps/isa-app/src/page/customer/validators/gender-b2b-validator.ts +++ b/apps/isa-app/src/page/customer/validators/gender-b2b-validator.ts @@ -1,17 +1,38 @@ import { UntypedFormGroup, ValidationErrors, ValidatorFn, Validators } from '@angular/forms'; -export function requiredIfControlIsSet( - requiredControlName: string, - ifSetControlName: string, -): ValidatorFn { - return (control: UntypedFormGroup): ValidationErrors | null => { - const requiredControl = control.get(requiredControlName); - const ifSetControl = control.get(ifSetControlName); +/** + * Angular form validator that requires a gender to be selected when a last name is provided. + * This validator is specifically designed for B2B forms where gender becomes mandatory + * only when personal information is entered. + * + * The validator looks for two specific form controls: + * - 'gender': The control that becomes required + * - 'lastName': The control that triggers the requirement + * + * @param control - The form group containing both 'gender' and 'lastName' controls + * @returns Validation errors if gender is missing when lastName is set, null otherwise + * + * @example + * ```typescript + * const form = new FormGroup({ + * gender: new FormControl(''), + * lastName: new FormControl(''), + * }, { + * validators: [requireGenderWhenNameIsSet] + * }); + * ``` + */ +export function requireGenderWhenNameIsSet(control: UntypedFormGroup): ValidationErrors | null { + const genderControl = control.get('gender'); + const nameControl = control.get('lastName'); - if (ifSetControl && ifSetControl.value) { - return Validators.required(requiredControl); + if (nameControl && !Validators.required(nameControl)) { + const errors = Validators.min(1)(genderControl) ? { required: true } : null; + + if (errors) { + genderControl.setErrors(errors); } - - return null; - }; + return errors; + } + return null; } diff --git a/apps/isa-app/src/ui/form-control/ui-form-control.component.ts b/apps/isa-app/src/ui/form-control/ui-form-control.component.ts index 0c9df4f66..44c061919 100644 --- a/apps/isa-app/src/ui/form-control/ui-form-control.component.ts +++ b/apps/isa-app/src/ui/form-control/ui-form-control.component.ts @@ -11,7 +11,7 @@ import { Output, } from '@angular/core'; import { NgControl } from '@angular/forms'; -import { combineLatest, Subscription } from 'rxjs'; +import { Subscription } from 'rxjs'; import { UiFormControlDirective } from './ui-form-control.directive'; @Component({ @@ -73,11 +73,15 @@ export class UiFormControlComponent implements AfterContentInit, OnDestroy { ngAfterContentInit() { if (this.ngControl) { this.subscriptions.add( - combineLatest([this.ngControl.control.statusChanges, this.ngControl.control.valueChanges]).subscribe( - (value) => { - this.cdr.markForCheck(); - }, - ), + this.ngControl.statusChanges.subscribe(() => { + this.cdr.markForCheck(); + }), + ); + + this.subscriptions.add( + this.ngControl.valueChanges.subscribe(() => { + this.cdr.markForCheck(); + }), ); } }