added form validation

This commit is contained in:
Igor Hrenowitsch Propisnov 2024-05-16 19:13:20 +02:00
parent 2c3db04acd
commit 0f1965dc29
4 changed files with 154 additions and 20 deletions

View File

@ -1,15 +1,15 @@
<div id="background"> <div id="background">
<div class="img-zone"> <div class="img-zone">
<div class="img-wrapper"> <div class="img-wrapper">
<h1>Hi, Welcome to Ticket App.</h1> <h1 (click)="DEBUG_restSignal()">Hi, Welcome to Ticket App.</h1>
</div> </div>
</div> </div>
<div class="content-zone"> <div class="content-zone">
<h1> <h1>
@if (this.isSignupSignal()) { @if (this.isSignupSignal()) {
Registrieren
} @else if (this.isRegisterSignal()) {
Anmelden Anmelden
} @else if (this.isRegisterSignal()) {
Registrieren
} @else { } @else {
Erste Schritte Erste Schritte
} }
@ -21,12 +21,45 @@
pButton pButton
type="button" type="button"
label="Anmelden" label="Anmelden"
(click)="toggleAction('register')"></button> (click)="toggleAction('signup')"></button>
<button <button
pButton pButton
type="button" type="button"
label="Registrieren" label="Registrieren"
(click)="toggleAction('signup')"></button> (click)="toggleAction('register')"></button>
</div>
}
@if (this.isSignupSignal()) {
<div class="register-wrapper">
<form [formGroup]="form" *ngIf="form" (ngSubmit)="onSubmit()">
<div class="e-mail">
<div class="label">
<label for="email">E-Mail</label>
</div>
<input
pInputText
id="email"
formControlName="email"
[ngClass]="{ 'ng-invalid ng-dirty': emailInvalid() }"
aria-describedby="e-mail" />
</div>
<div class="password">
<div class="label">
<label for="password">Password</label>
</div>
<input
pInputText
id="password"
formControlName="password"
aria-describedby="password"
[ngClass]="{ 'ng-invalid ng-dirty': passwordInvalid() }"
type="password" />
</div>
<div class="signup">
<button pButton type="submit" label="Anmelden"></button>
</div>
</form>
</div> </div>
} }
@ -41,6 +74,7 @@
pInputText pInputText
id="email" id="email"
formControlName="email" formControlName="email"
[ngClass]="{ 'ng-invalid ng-dirty': emailInvalid() }"
aria-describedby="e-mail" /> aria-describedby="e-mail" />
</div> </div>
<div class="password"> <div class="password">
@ -52,10 +86,22 @@
id="password" id="password"
formControlName="password" formControlName="password"
aria-describedby="password" aria-describedby="password"
[ngClass]="{ 'ng-invalid ng-dirty': passwordInvalid() }"
type="password" /> type="password" />
</div> </div>
<div class="terms">
<p-checkbox
formControlName="terms"
label="Ich habe die AGB gelesen und stimme zu."
name="terms"
[ngClass]="{ 'ng-invalid ng-dirty': termsInvalid() }"
[binary]="true" />
</div>
<div class="signup"> <div class="signup">
<button pButton type="submit" label="Anmelden"></button> <button
pButton
type="submit"
label="✨ Jetzt KOSTENFREI registrieren ✨"></button>
</div> </div>
</form> </form>
</div> </div>

View File

@ -53,9 +53,10 @@
} }
.e-mail, .e-mail,
.password { .password,
.terms {
.label { .label {
font-size: 1.5em; font-size: 1;
} }
input { input {
@ -63,8 +64,12 @@
} }
} }
.terms {
padding-top: 1.33em;
}
.password { .password {
padding-top: 3em; padding-top: 2em;
} }
.signup { .signup {
@ -76,3 +81,12 @@
} }
} }
} }
// .ng-invalid.ng-dirty {
// border: 1px solid red;
// }
// .error {
// color: red;
// font-size: 12px;
// }

View File

@ -5,16 +5,22 @@ import {
OnInit, OnInit,
WritableSignal, WritableSignal,
signal, signal,
effect,
DestroyRef,
} from '@angular/core'; } from '@angular/core';
import { InputTextModule } from 'primeng/inputtext'; import { InputTextModule } from 'primeng/inputtext';
import { import {
FormBuilder, FormBuilder,
FormControl,
FormGroup, FormGroup,
FormsModule, FormsModule,
ReactiveFormsModule, ReactiveFormsModule,
Validators, Validators,
} from '@angular/forms'; } from '@angular/forms';
import { ButtonModule } from 'primeng/button'; import { ButtonModule } from 'primeng/button';
import { CheckboxModule } from 'primeng/checkbox';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { debounceTime } from 'rxjs/operators';
type AuthAction = 'register' | 'signup'; type AuthAction = 'register' | 'signup';
@ -27,6 +33,7 @@ type AuthAction = 'register' | 'signup';
InputTextModule, InputTextModule,
ReactiveFormsModule, ReactiveFormsModule,
ButtonModule, ButtonModule,
CheckboxModule,
], ],
templateUrl: './register-root.component.html', templateUrl: './register-root.component.html',
styleUrl: './register-root.component.scss', styleUrl: './register-root.component.scss',
@ -34,27 +41,91 @@ type AuthAction = 'register' | 'signup';
}) })
export class RegisterRootComponent implements OnInit { export class RegisterRootComponent implements OnInit {
public form: FormGroup | undefined; public form: FormGroup | undefined;
public isRegisterSignal: WritableSignal<boolean> = signal(false); public isRegisterSignal: WritableSignal<boolean> = signal(false);
public isSignupSignal: WritableSignal<boolean> = signal(false); public isSignupSignal: WritableSignal<boolean> = signal(false);
public isDisplayButtons: WritableSignal<boolean> = signal(true); public isDisplayButtons: WritableSignal<boolean> = signal(true);
constructor(private readonly formBuilder: FormBuilder) {} public emailInvalid: WritableSignal<boolean | null> = signal(true);
public passwordInvalid: WritableSignal<boolean | null> = signal(null);
public termsInvalid: WritableSignal<boolean | null> = signal(null);
ngOnInit() { constructor(
this.form = this.formBuilder.group({ private readonly formBuilder: FormBuilder,
email: ['', [Validators.required, Validators.email]], private readonly destroyRef: DestroyRef
password: ['', [Validators.required, Validators.minLength(6)]], ) {
effect(() => {
if (this.form) {
if (this.isRegisterSignal()) {
this.form.addControl(
'terms',
new FormControl(false, Validators.requiredTrue)
);
} else {
this.form.removeControl('terms');
}
}
}); });
} }
public toggleAction(action: AuthAction) { public ngOnInit(): void {
const isRegister = action === 'register'; this.form = this.formBuilder.group({
this.isRegisterSignal.set(isRegister); email: ['', [Validators.required, Validators.email]],
this.isSignupSignal.set(!isRegister); password: ['', [Validators.required, Validators.minLength(6)]],
terms: [false, [Validators.requiredTrue]],
});
this.form.statusChanges
.pipe(debounceTime(500), takeUntilDestroyed(this.destroyRef))
.subscribe(() => {
this.updateFieldInvalidity();
});
}
public toggleAction(action: AuthAction): void {
if (action === 'register') {
this.isRegisterSignal.set(true);
this.isSignupSignal.set(false);
} else {
this.isRegisterSignal.set(false);
this.isSignupSignal.set(true);
}
this.isDisplayButtons.set(false); this.isDisplayButtons.set(false);
} }
public onSubmit() { public onSubmit(): void {
console.log('signup'); this.form?.markAllAsTouched();
this.updateFieldInvalidity();
if (this.isSignupSignal() && this.form?.valid) {
this.signin();
} else if (this.isRegisterSignal() && this.form?.valid) {
this.register();
}
}
public DEBUG_restSignal(): void {
this.isRegisterSignal.set(false);
this.isSignupSignal.set(false);
this.isDisplayButtons.set(true);
}
private updateFieldInvalidity(): void {
this.emailInvalid.set(this.isFieldInvalid('email'));
this.passwordInvalid.set(this.isFieldInvalid('password'));
this.termsInvalid.set(this.isFieldInvalid('terms'));
}
private isFieldInvalid(field: string): boolean {
const formField = this.form?.get(field);
return !!formField && !formField.valid && formField.touched;
}
private signin(): void {
console.log('Signin...');
}
private register(): void {
console.log('Register...');
} }
} }

View File

@ -2,6 +2,9 @@
@import 'primeng/resources/themes/lara-light-blue/theme.css'; @import 'primeng/resources/themes/lara-light-blue/theme.css';
@import 'primeng/resources/primeng.css'; @import 'primeng/resources/primeng.css';
// PrimeNG icons
@import 'primeicons/primeicons.css';
html, html,
body { body {
height: 100%; height: 100%;