Skip to content
Snippets Groups Projects
Verified Commit d38c4d4f authored by Sebastian Bergandy's avatar Sebastian Bergandy :keyboard:
Browse files

wip albert sebo validation

parent 2d8e5b09
No related branches found
No related tags found
No related merge requests found
...@@ -21,7 +21,13 @@ ...@@ -21,7 +21,13 @@
* Die sprachspezifischen Genehmigungen und Beschränkungen * Die sprachspezifischen Genehmigungen und Beschränkungen
* unter der Lizenz sind dem Lizenztext zu entnehmen. * unter der Lizenz sind dem Lizenztext zu entnehmen.
*/ */
import { createEmptyStateResource, InvalidParam, isLoaded, setInvalidParamValidationError, StateResource, } from '@alfa-client/tech-shared'; import {
createEmptyStateResource,
InvalidParam,
isLoaded,
setInvalidParamValidationError,
StateResource,
} from '@alfa-client/tech-shared';
import { inject, Injectable } from '@angular/core'; import { inject, Injectable } from '@angular/core';
import { AbstractControl, FormArray, FormBuilder, FormGroup } from '@angular/forms'; import { AbstractControl, FormArray, FormBuilder, FormGroup } from '@angular/forms';
import { ActivatedRoute, UrlSegment } from '@angular/router'; import { ActivatedRoute, UrlSegment } from '@angular/router';
...@@ -72,16 +78,24 @@ export abstract class KeycloakFormService<T> { ...@@ -72,16 +78,24 @@ export abstract class KeycloakFormService<T> {
} }
public submit(): Observable<StateResource<T>> { public submit(): Observable<StateResource<T>> {
console.info('value before update and validity: %o', this.form.value);
this._showValidationErrorForAllInvalidControls(this.form);
console.info('value after update and validity: %o', this.form.value);
setTimeout(() => {
console.info('form after timeout valid = %s, value = %o', this.form.valid, this.form.value);
}, 0);
if (this.form.invalid) { if (this.form.invalid) {
console.info('form INVALID');
return this._processInvalidForm(); return this._processInvalidForm();
} }
console.info('form VALID');
return this._doSubmit().pipe( return this._doSubmit().pipe(
catchError((keycloakError: KeycloakHttpErrorResponse) => this._processResponseValidationErrors(keycloakError)), catchError((keycloakError: KeycloakHttpErrorResponse) => this._processResponseValidationErrors(keycloakError)),
); );
} }
_processInvalidForm(): Observable<StateResource<T>> { _processInvalidForm(): Observable<StateResource<T>> {
this._showValidationErrorForAllInvalidControls(this.form); // this._showValidationErrorForAllInvalidControls(this.form);
return of(createEmptyStateResource<T>()); return of(createEmptyStateResource<T>());
} }
...@@ -98,7 +112,8 @@ export abstract class KeycloakFormService<T> { ...@@ -98,7 +112,8 @@ export abstract class KeycloakFormService<T> {
} }
_showValidationErrorForAllInvalidControls(control: AbstractControl): void { _showValidationErrorForAllInvalidControls(control: AbstractControl): void {
if (control.invalid) control.updateValueAndValidity(); // if (control.invalid)
control.updateValueAndValidity();
if (control instanceof FormGroup || control instanceof FormArray) { if (control instanceof FormGroup || control instanceof FormArray) {
Object.values(control.controls).forEach((control) => this._showValidationErrorForAllInvalidControls(control)); Object.values(control.controls).forEach((control) => this._showValidationErrorForAllInvalidControls(control));
} }
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
unter der Lizenz sind dem Lizenztext zu entnehmen. unter der Lizenz sind dem Lizenztext zu entnehmen.
--> -->
<form [formGroup]="formService.form">
<ods-spinner [stateResource]="userStateResource$ | async"> <ods-spinner [stateResource]="userStateResource$ | async">
<div class="max-w-[960px]" data-test-id="user-content"> <div class="max-w-[960px]" data-test-id="user-content">
<admin-user-form-headline [isPatch]="isPatch" /> <admin-user-form-headline [isPatch]="isPatch" />
...@@ -40,3 +41,4 @@ ...@@ -40,3 +41,4 @@
</div> </div>
</div> </div>
</ods-spinner> </ods-spinner>
</form>
...@@ -32,19 +32,10 @@ import { ...@@ -32,19 +32,10 @@ import {
PatchConfig, PatchConfig,
} from '@admin/keycloak-shared'; } from '@admin/keycloak-shared';
import { NavigationService } from '@alfa-client/navigation-shared'; import { NavigationService } from '@alfa-client/navigation-shared';
import { import { EMPTY_STRING, isLoaded, mapToResource, StateResource } from '@alfa-client/tech-shared';
checkBoxGroupsEmptyValidator,
EMPTY_STRING,
fieldEmptyValidator,
fieldInvalidValidator,
fieldLengthValidator,
isLoaded,
mapToResource,
StateResource,
} from '@alfa-client/tech-shared';
import { SnackBarService } from '@alfa-client/ui'; import { SnackBarService } from '@alfa-client/ui';
import { Injectable, OnDestroy } from '@angular/core'; import { Injectable, OnDestroy } from '@angular/core';
import { AbstractControl, FormControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { AbstractControl, FormControl, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { UrlSegment } from '@angular/router'; import { UrlSegment } from '@angular/router';
import { filter, Observable, Subscription, tap } from 'rxjs'; import { filter, Observable, Subscription, tap } from 'rxjs';
...@@ -100,15 +91,13 @@ export class UserFormService extends KeycloakFormService<User> implements OnDest ...@@ -100,15 +91,13 @@ export class UserFormService extends KeycloakFormService<User> implements OnDest
} }
_initForm(): UntypedFormGroup { _initForm(): UntypedFormGroup {
return this.formBuilder.group({ return this.formBuilder.group(
[UserFormService.FIRST_NAME]: new FormControl(EMPTY_STRING, fieldEmptyValidator(UserFormService.FIRST_NAME)),
[UserFormService.LAST_NAME]: new FormControl(EMPTY_STRING, fieldEmptyValidator(UserFormService.LAST_NAME)),
[UserFormService.USERNAME]: new FormControl(EMPTY_STRING, [fieldLengthValidator(UserFormService.USERNAME, 3, 255)]),
[UserFormService.EMAIL]: new FormControl(EMPTY_STRING, [
fieldInvalidValidator(UserFormService.EMAIL, /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/),
]),
[UserFormService.CLIENT_ROLES]: this.formBuilder.group(
{ {
[UserFormService.FIRST_NAME]: new FormControl(EMPTY_STRING, Validators.required),
[UserFormService.LAST_NAME]: new FormControl(EMPTY_STRING),
[UserFormService.USERNAME]: new FormControl(EMPTY_STRING),
[UserFormService.EMAIL]: new FormControl(EMPTY_STRING),
[UserFormService.CLIENT_ROLES]: this.formBuilder.group({
[UserFormService.ADMINISTRATION_GROUP]: this.formBuilder.group({ [UserFormService.ADMINISTRATION_GROUP]: this.formBuilder.group({
[UserFormService.ADMIN]: new FormControl(false), [UserFormService.ADMIN]: new FormControl(false),
[UserFormService.DATENBEAUFTRAGUNG]: new FormControl(false), [UserFormService.DATENBEAUFTRAGUNG]: new FormControl(false),
...@@ -118,16 +107,11 @@ export class UserFormService extends KeycloakFormService<User> implements OnDest ...@@ -118,16 +107,11 @@ export class UserFormService extends KeycloakFormService<User> implements OnDest
[UserFormService.USER]: new FormControl(false), [UserFormService.USER]: new FormControl(false),
[UserFormService.POSTSTELLE]: new FormControl(false), [UserFormService.POSTSTELLE]: new FormControl(false),
}), }),
}, }),
{
validators: checkBoxGroupsEmptyValidator(UserFormService.CLIENT_ROLES, [
UserFormService.ADMINISTRATION_GROUP,
UserFormService.ALFA_GROUP,
]),
},
),
[UserFormService.GROUPS]: this.formBuilder.group({}), [UserFormService.GROUPS]: this.formBuilder.group({}),
}); },
{ updateOn: 'submit' },
);
} }
_initOrganisationsEinheiten(): Observable<AdminOrganisationsEinheit[]> { _initOrganisationsEinheiten(): Observable<AdminOrganisationsEinheit[]> {
......
...@@ -45,13 +45,20 @@ export abstract class FormControlEditorAbstractComponent implements ControlValue ...@@ -45,13 +45,20 @@ export abstract class FormControlEditorAbstractComponent implements ControlValue
this.changesSubscr = this.fieldControl.valueChanges.subscribe((val) => { this.changesSubscr = this.fieldControl.valueChanges.subscribe((val) => {
this.onChange(val); this.onChange(val);
this.setErrors(); // if (this.control?.control && this.control.control.getRawValue() !== this.fieldControl.value) {
// this.control.control.setValue(this.fieldControl.value, { emitEvent: false });
// }
this.fieldControl.setErrors(null);
this.invalidParams = [];
}); });
} }
ngOnInit(): void { ngOnInit(): void {
if (!this.statusSubscr && this.control) if (!this.statusSubscr && this.control)
this.statusSubscr = this.control.statusChanges.subscribe(() => { this.statusSubscr = this.control.statusChanges.subscribe(() => {
this.onChange(this.fieldControl.value);
this.fieldControl.updateValueAndValidity({ emitEvent: false });
this.control.control.updateValueAndValidity({ emitEvent: false });
this.setErrors(); this.setErrors();
}); });
} }
...@@ -62,7 +69,6 @@ export abstract class FormControlEditorAbstractComponent implements ControlValue ...@@ -62,7 +69,6 @@ export abstract class FormControlEditorAbstractComponent implements ControlValue
writeValue(text: string): void { writeValue(text: string): void {
this.fieldControl.setValue(text); this.fieldControl.setValue(text);
this.setErrors();
} }
registerOnChange(fn: (text: string | Date) => {}): void { registerOnChange(fn: (text: string | Date) => {}): void {
......
...@@ -105,7 +105,7 @@ export type ButtonVariants = VariantProps<typeof buttonVariants>; ...@@ -105,7 +105,7 @@ export type ButtonVariants = VariantProps<typeof buttonVariants>;
standalone: true, standalone: true,
imports: [CommonModule, SpinnerIconComponent], imports: [CommonModule, SpinnerIconComponent],
template: ` <button template: ` <button
type="button" type="submit"
[ngClass]="buttonVariants({ size, variant, disabled: isDisabled, destructive })" [ngClass]="buttonVariants({ size, variant, disabled: isDisabled, destructive })"
[attr.aria-disabled]="isDisabled" [attr.aria-disabled]="isDisabled"
[attr.aria-label]="text" [attr.aria-label]="text"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment