error messages kinda
This commit is contained in:
parent
71612b1a9c
commit
2503c33005
@ -11,6 +11,8 @@ import {
|
|||||||
import {Hotel} from "../model/hotel";
|
import {Hotel} from "../model/hotel";
|
||||||
import {RouterLink} from "@angular/router";
|
import {RouterLink} from "@angular/router";
|
||||||
import {NgForOf} from "@angular/common";
|
import {NgForOf} from "@angular/common";
|
||||||
|
import {debounceTime} from "rxjs";
|
||||||
|
import {ErrorMsgComponent} from "./error-msg.component";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-edit-hotel',
|
selector: 'app-edit-hotel',
|
||||||
@ -20,24 +22,29 @@ import {NgForOf} from "@angular/common";
|
|||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
RouterLink,
|
RouterLink,
|
||||||
NgForOf,
|
NgForOf,
|
||||||
|
ErrorMsgComponent,
|
||||||
],
|
],
|
||||||
template: `
|
template: `
|
||||||
<ng-form [formGroup]="form" (ngSubmit)="submit()">
|
<ng-form [formGroup]="form" (ngSubmit)="submit()">
|
||||||
<label for="name">Name</label>
|
<label for="name">Name</label>
|
||||||
<br>
|
<br>
|
||||||
<input id="name" type="text" formControlName="name">
|
<input id="name" type="text" formControlName="name">
|
||||||
|
<app-error-msg [msg]="errorMsgs['name']"></app-error-msg>
|
||||||
<br>
|
<br>
|
||||||
<label for="description">Description</label>
|
<label for="description">Description</label>
|
||||||
<br>
|
<br>
|
||||||
<input id="description" type="text" formControlName="description">
|
<input id="description" type="text" formControlName="description">
|
||||||
|
<app-error-msg [msg]="errorMsgs['description']"></app-error-msg>
|
||||||
<br>
|
<br>
|
||||||
<label for="price">Price</label>
|
<label for="price">Price</label>
|
||||||
<br>
|
<br>
|
||||||
<input id="price" type="number" formControlName="price">
|
<input id="price" type="number" formControlName="price">
|
||||||
|
<app-error-msg [msg]="errorMsgs['price']"></app-error-msg>
|
||||||
<br>
|
<br>
|
||||||
<label for="rating">Rating</label>
|
<label for="rating">Rating</label>
|
||||||
<br>
|
<br>
|
||||||
<input id="rating" type="number" formControlName="rating" min="0" max="5">
|
<input id="rating" type="number" formControlName="rating" min="0" max="5">
|
||||||
|
<app-error-msg [msg]="errorMsgs['rating']"></app-error-msg>
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
<button (click)="addTag()">+</button>
|
<button (click)="addTag()">+</button>
|
||||||
@ -46,6 +53,7 @@ import {NgForOf} from "@angular/common";
|
|||||||
<input type="text" placeholder="tag" [formControlName]="i">
|
<input type="text" placeholder="tag" [formControlName]="i">
|
||||||
<button (click)="deleteTag(tag)">-</button>
|
<button (click)="deleteTag(tag)">-</button>
|
||||||
</div>
|
</div>
|
||||||
|
<app-error-msg [msg]="errorMsgs['tags']"></app-error-msg>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
@ -56,6 +64,8 @@ import {NgForOf} from "@angular/common";
|
|||||||
`,
|
`,
|
||||||
})
|
})
|
||||||
export class EditHotelComponent implements OnInit {
|
export class EditHotelComponent implements OnInit {
|
||||||
|
errorMsgs: Record<string, string> = {};
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
hotel: Hotel | null = null;
|
hotel: Hotel | null = null;
|
||||||
|
|
||||||
@ -64,6 +74,12 @@ export class EditHotelComponent implements OnInit {
|
|||||||
|
|
||||||
form!: FormGroup
|
form!: FormGroup
|
||||||
|
|
||||||
|
validationErrors: Record<string, string> = {
|
||||||
|
required: 'This field is required',
|
||||||
|
min: 'Value must be greater than or equal to 0',
|
||||||
|
max: 'Value must be less than or equal to 5'
|
||||||
|
};
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
const tags = [];
|
const tags = [];
|
||||||
|
|
||||||
@ -78,15 +94,20 @@ export class EditHotelComponent implements OnInit {
|
|||||||
rating: new FormControl(this.hotel?.rating, [Validators.required, Validators.min(0), Validators.max(5)]),
|
rating: new FormControl(this.hotel?.rating, [Validators.required, Validators.min(0), Validators.max(5)]),
|
||||||
tags: new FormArray(tags),
|
tags: new FormArray(tags),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Object.keys(this.form.controls).forEach(controlName => {
|
||||||
|
const control = this.form.get(controlName);
|
||||||
|
if (!control) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
control?.valueChanges?.pipe(debounceTime(1000)).subscribe(() => {this.setErrorMessage(controlName, control)});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
submit() {
|
submit() {
|
||||||
if (!this.form.valid) {
|
if (!this.form.valid) {
|
||||||
console.error('Form invalid: ');
|
|
||||||
for (const key in this.form.controls) {
|
|
||||||
console.error(key, this.form.controls[key].errors);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const hotel: Hotel = {
|
const hotel: Hotel = {
|
||||||
@ -115,4 +136,8 @@ export class EditHotelComponent implements OnInit {
|
|||||||
deleteTag(tagElement: AbstractControl) {
|
deleteTag(tagElement: AbstractControl) {
|
||||||
this.getTags().removeAt(this.getTags().controls.indexOf(tagElement));
|
this.getTags().removeAt(this.getTags().controls.indexOf(tagElement));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setErrorMessage(controlName: string, control: AbstractControl) {
|
||||||
|
this.errorMsgs[controlName] = Object.keys(control.errors ?? {}).map ((key) => this.validationErrors[key]).join(' ');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
32
src/app/hotel/component/error-msg.component.ts
Normal file
32
src/app/hotel/component/error-msg.component.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import {Component, Input} from "@angular/core";
|
||||||
|
import {NgIf} from "@angular/common";
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
standalone: true,
|
||||||
|
selector: 'app-error-msg',
|
||||||
|
imports: [
|
||||||
|
NgIf
|
||||||
|
],
|
||||||
|
template: `
|
||||||
|
<div *ngIf="msg" class="alert alert-danger">
|
||||||
|
{{ msg }}
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
styles: `
|
||||||
|
.alert {
|
||||||
|
color: white;
|
||||||
|
background-color: red;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-danger {
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
})
|
||||||
|
export class ErrorMsgComponent {
|
||||||
|
@Input()
|
||||||
|
msg: string | null = null;
|
||||||
|
}
|
@ -8,7 +8,6 @@
|
|||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/js/bootstrap.min.js" integrity="sha512-ykZ1QQr0Jy/4ZkvKuqWn4iF3lqPZyij9iRv6sGqLRdTPkY69YX6+7wvVGmsdBbiIfN/8OdsI7HABjvEok6ZopQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/js/bootstrap.min.js" integrity="sha512-ykZ1QQr0Jy/4ZkvKuqWn4iF3lqPZyij9iRv6sGqLRdTPkY69YX6+7wvVGmsdBbiIfN/8OdsI7HABjvEok6ZopQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/css/bootstrap-grid.min.css" integrity="sha512-i1b/nzkVo97VN5WbEtaPebBG8REvjWeqNclJ6AItj7msdVcaveKrlIIByDpvjk5nwHjXkIqGZscVxOrTb9tsMA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/css/bootstrap-grid.min.css" integrity="sha512-i1b/nzkVo97VN5WbEtaPebBG8REvjWeqNclJ6AItj7msdVcaveKrlIIByDpvjk5nwHjXkIqGZscVxOrTb9tsMA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/material-design-icons/4.0.0/iconfont/material-icons.min.css" referrerpolicy="no-referrer" />
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<app-root></app-root>
|
<app-root></app-root>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user