Skip to content

Commit

Permalink
added input validation
Browse files Browse the repository at this point in the history
  • Loading branch information
ortwic committed Apr 19, 2024
1 parent 57b242f commit 8d4e43d
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 36 deletions.
63 changes: 39 additions & 24 deletions src/app/components/input-section/input-section.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,48 @@
{{item.value.caption}}
</mat-card-title>
</mat-card-header>
<mat-card-content class="content">
@if(item.type === 'select') {
<mat-card-content class="content">
<mat-button-toggle-group class="select-group"
[ngClass]="{'wrap-options': item.value.multiline}"
<mat-button-toggle-group class="select-group"
[ngClass]="{'wrap-options': item.value.multiline}"
[name]="item.value.id"
[multiple]="item.value.multiple"
[disabled]="disabled"
[ngModel]="value"
(ngModelChange)="updateValue($event)">
@for(opt of item.value.options; track $index) {
<mat-button-toggle [value]="opt">
{{opt}}
</mat-button-toggle>
}
</mat-button-toggle-group>
} @else if (item.type === 'textarea') {
<mat-form-field class="field" appearance="outline">
<textarea matInput
[name]="item.value.id"
[multiple]="item.value.multiple"
[disabled]="disabled"
[placeholder]="item.value.placeholder"
[pattern]="item.value.validation"
[ngModel]="value"
(ngModelChange)="updateValue($event)">
@for(opt of item.value.options; track $index) {
<mat-button-toggle [value]="opt">
{{opt}}
</mat-button-toggle>
}
</mat-button-toggle-group>
</mat-card-content>
} @else if (item.type === 'textarea') {
<mat-card-content class="content">
<mat-form-field class="field" appearance="outline">
<textarea matInput
[name]="item.value.id"
[disabled]="disabled"
[placeholder]="item.value.placeholder"
[ngModel]="value"
(ngModelChange)="updateValue($event)"
></textarea>
</mat-form-field>
</mat-card-content>
(ngModelChange)="updateValue($event)"
></textarea>
<mat-error *ngIf="!valid">
{{validationMessage}}
</mat-error>
</mat-form-field>
} @else if (item.type === 'text') {
<mat-form-field class="field" appearance="outline">
<input type="text" matInput
[name]="item.value.id"
[disabled]="disabled"
[placeholder]="item.value.placeholder"
[pattern]="item.value.validation"
[ngModel]="value"
(ngModelChange)="updateValue($event)"/>
<mat-error *ngIf="!valid">
{{validationMessage}}
</mat-error>
</mat-form-field>
}
</mat-card-content>
</mat-card>
15 changes: 15 additions & 0 deletions src/app/components/input-section/input-section.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
6 changes: 3 additions & 3 deletions src/app/components/input-stepper/input-stepper.component.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<section>
@for (item of definitions; track $index) {
<div [@next]="show($index)">
<app-input-section [item]="item" [name]="item.value.id" [disabled]="disabled($index)"
<app-input-section [item]="item" [name]="item.value.id" [disabled]="!isActive($index)"
[ngModel]="data[item.value.id]" (ngModelChange)="update($event, item.value.id)" />
</div>
}
<span class="footer">
<app-progress-spinner [@next]="!done ? 'expanded' : 'collapsed'" [value]="progress" [size]="60">
<button mat-icon-button class="next" color="primary"
<app-progress-spinner [@next]="!done ? 'expanded' : 'collapsed'" [disabled]="disabled" [value]="progress" [size]="60">
<button mat-icon-button class="next" color="primary" [disabled]="disabled"
[title]="last ? 'Fertig' : 'Weiter'" (click)="next();">
<mat-icon [fontIcon]="last ? 'check' : 'arrow_downward'" />
</button>
Expand Down
15 changes: 12 additions & 3 deletions src/app/components/input-stepper/input-stepper.component.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -32,8 +32,10 @@ export class InputStepperComponent {
@Input({ required: true }) definitions!: InputDefinition[];
@Input() data: Record<string, InputValue> = {};
@Output() continue = new EventEmitter<ContinueEventArgs>();
@ViewChildren(InputSectionComponent) inputs!: QueryList<InputSectionComponent>;

done = false;
disabled = true;
private _step = 0;

get last(): boolean {
Expand All @@ -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 {
Expand All @@ -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,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<div class="element">
<mat-progress-spinner [color] [diameter]="size" [value]="value" mode="determinate" />
<div class="element" [ngClass]="{ 'disabled': disabled }">
<mat-progress-spinner [ariaDisabled]="disabled" [color]="color"
[diameter]="size" [value]="value" mode="determinate" />
<div class="content">
<ng-content></ng-content>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,9 @@
transform: translate(-50%, -50%);
z-index: 1;
}

&.disabled {
filter: grayscale(1);
opacity: .5;
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { CommonModule } from '@angular/common';
import { Component, Input } from '@angular/core';
import { MatIconModule } from '@angular/material/icon';
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'
})
export class ProgressSpinnerComponent {
@Input() color = 'primary';
@Input() size = 40;
@Input() value = 0;
@Input() disabled = false;
}
8 changes: 5 additions & 3 deletions src/app/models/content.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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;
};
}
10 changes: 10 additions & 0 deletions src/styles/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ img.marked-image {

p {
line-height: 1.33;
hyphens: auto;
}

strong {
font-weight: 600;
}

blockquote {
Expand All @@ -62,6 +67,11 @@ blockquote {
}
}

ul li {
padding: .3rem 0;
hyphens: auto;
}

pre.wp-block-verse {
border-radius: 1rem;
background-color: var(--bg3);
Expand Down

0 comments on commit 8d4e43d

Please sign in to comment.