From 8d4e43dd0db955873457f4acb858c423ca4748c8 Mon Sep 17 00:00:00 2001 From: Ortwin Date: Fri, 19 Apr 2024 12:06:05 +0200 Subject: [PATCH] added input validation --- .../input-section.component.html | 63 ++++++++++++------- .../input-section/input-section.component.ts | 15 +++++ .../input-stepper.component.html | 6 +- .../input-stepper/input-stepper.component.ts | 15 ++++- .../progress-spinner.component.html | 5 +- .../progress-spinner.component.scss | 5 ++ .../progress-spinner.component.ts | 4 +- src/app/models/content.model.ts | 8 ++- src/styles/main.scss | 10 +++ 9 files changed, 95 insertions(+), 36 deletions(-) diff --git a/src/app/components/input-section/input-section.component.html b/src/app/components/input-section/input-section.component.html index 304a3e0..14064e9 100644 --- a/src/app/components/input-section/input-section.component.html +++ b/src/app/components/input-section/input-section.component.html @@ -4,33 +4,48 @@ {{item.value.caption}} + @if(item.type === 'select') { - - + @for(opt of item.value.options; track $index) { + + {{opt}} + + } + + } @else if (item.type === 'textarea') { + + - - + (ngModelChange)="updateValue($event)" + > + + {{validationMessage}} + + + } @else if (item.type === 'text') { + + + + {{validationMessage}} + + } + \ No newline at end of file diff --git a/src/app/components/input-section/input-section.component.ts b/src/app/components/input-section/input-section.component.ts index 254d20a..efec7ce 100644 --- a/src/app/components/input-section/input-section.component.ts +++ b/src/app/components/input-section/input-section.component.ts @@ -36,6 +36,21 @@ export class InputSectionComponent implements ControlValueAccessor { @Input('ngModel') value!: InputValue; @Output('ngModelChange') change = new EventEmitter(); + get valid(): boolean { + if ('validation' in this.item.value && this.item.value.validation) { + const pattern = new RegExp(this.item.value.validation); + return pattern.test(`${this.value}`); + } + return true; + } + + get validationMessage(): string { + if ('message' in this.item.value) { + return this.item.value.message; + } + return 'Eingabe ungültig'; + } + writeValue(value: InputValue): void { this.value = value; } diff --git a/src/app/components/input-stepper/input-stepper.component.html b/src/app/components/input-stepper/input-stepper.component.html index 5b78d7e..e96117a 100644 --- a/src/app/components/input-stepper/input-stepper.component.html +++ b/src/app/components/input-stepper/input-stepper.component.html @@ -1,13 +1,13 @@
@for (item of definitions; track $index) {
-
} - - diff --git a/src/app/components/input-stepper/input-stepper.component.ts b/src/app/components/input-stepper/input-stepper.component.ts index 414beba..f0a2968 100644 --- a/src/app/components/input-stepper/input-stepper.component.ts +++ b/src/app/components/input-stepper/input-stepper.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { Component, EventEmitter, Input, Output, QueryList, ViewChildren } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { MatButtonModule } from '@angular/material/button'; @@ -32,8 +32,10 @@ export class InputStepperComponent { @Input({ required: true }) definitions!: InputDefinition[]; @Input() data: Record = {}; @Output() continue = new EventEmitter(); + @ViewChildren(InputSectionComponent) inputs!: QueryList; done = false; + disabled = true; private _step = 0; get last(): boolean { @@ -48,12 +50,18 @@ export class InputStepperComponent { return index <= this._step ? 'expanded' : 'collapsed'; } - disabled(index: number): boolean { - return index !== this._step; + isActive(index: number): boolean { + return index === this._step; + } + + isValid(): boolean { + const currentInput = this.inputs?.get(this._step); + return currentInput ? currentInput.valid : true; } update(value: InputValue, id: string) { this.data[id] = value; + this.disabled = !this.isValid(); } next(): void { @@ -64,6 +72,7 @@ export class InputStepperComponent { } this._step++; + this.disabled = !this.isValid(); this.done = this._step === this.definitions.length; this.continue.emit({ completed: this.done, diff --git a/src/app/components/ui/progress-spinner/progress-spinner.component.html b/src/app/components/ui/progress-spinner/progress-spinner.component.html index 91107cb..d37f5b8 100644 --- a/src/app/components/ui/progress-spinner/progress-spinner.component.html +++ b/src/app/components/ui/progress-spinner/progress-spinner.component.html @@ -1,5 +1,6 @@ -
- +
+
diff --git a/src/app/components/ui/progress-spinner/progress-spinner.component.scss b/src/app/components/ui/progress-spinner/progress-spinner.component.scss index 329c43e..2600a9d 100644 --- a/src/app/components/ui/progress-spinner/progress-spinner.component.scss +++ b/src/app/components/ui/progress-spinner/progress-spinner.component.scss @@ -10,4 +10,9 @@ transform: translate(-50%, -50%); z-index: 1; } + + &.disabled { + filter: grayscale(1); + opacity: .5; + } } \ No newline at end of file diff --git a/src/app/components/ui/progress-spinner/progress-spinner.component.ts b/src/app/components/ui/progress-spinner/progress-spinner.component.ts index a70bfdb..f0621ac 100644 --- a/src/app/components/ui/progress-spinner/progress-spinner.component.ts +++ b/src/app/components/ui/progress-spinner/progress-spinner.component.ts @@ -1,3 +1,4 @@ +import { CommonModule } from '@angular/common'; import { Component, Input } from '@angular/core'; import { MatIconModule } from '@angular/material/icon'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; @@ -5,7 +6,7 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; @Component({ selector: 'app-progress-spinner', standalone: true, - imports: [MatIconModule, MatProgressSpinnerModule], + imports: [CommonModule, MatIconModule, MatProgressSpinnerModule], templateUrl: './progress-spinner.component.html', styleUrl: './progress-spinner.component.scss' }) @@ -13,4 +14,5 @@ export class ProgressSpinnerComponent { @Input() color = 'primary'; @Input() size = 40; @Input() value = 0; + @Input() disabled = false; } diff --git a/src/app/models/content.model.ts b/src/app/models/content.model.ts index 80a2662..5f6936c 100644 --- a/src/app/models/content.model.ts +++ b/src/app/models/content.model.ts @@ -60,7 +60,7 @@ export interface FormContent { value: InputDefinition[]; } -export type InputDefinition = SelectList | Textarea; +export type InputDefinition = SelectList | TextField; export type InputValue = string[] | string | number | boolean | undefined; interface SelectList { @@ -74,11 +74,13 @@ interface SelectList { }; } -interface Textarea { - type: 'textarea'; +interface TextField { + type: 'text' | 'textarea'; value: { id: string; caption: string; placeholder: string; + validation: string; + message: string; }; } \ No newline at end of file diff --git a/src/styles/main.scss b/src/styles/main.scss index 9177713..5d7bcde 100644 --- a/src/styles/main.scss +++ b/src/styles/main.scss @@ -42,6 +42,11 @@ img.marked-image { p { line-height: 1.33; + hyphens: auto; +} + +strong { + font-weight: 600; } blockquote { @@ -62,6 +67,11 @@ blockquote { } } +ul li { + padding: .3rem 0; + hyphens: auto; +} + pre.wp-block-verse { border-radius: 1rem; background-color: var(--bg3);