BookMonkey 3 Diff

Files changed (6) hide show
  1. tmp/src/app/book-monkey/iteration-4/{reactive-forms → custom-validation}/book-form/book-form.component.ts +15 -7
  2. tmp/src/app/book-monkey/iteration-4/{reactive-forms → custom-validation}/create-book/create-book.component.ts +0 -1
  3. tmp/src/app/book-monkey/iteration-4/{reactive-forms → custom-validation}/form-messages/form-messages.component.ts +3 -3
  4. tmp/src/app/book-monkey/iteration-4/{reactive-forms → custom-validation}/shared/book-exists-validator.service.ts +25 -0
  5. tmp/src/app/book-monkey/iteration-4/{reactive-forms → custom-validation}/shared/book-store.service.ts +8 -0
  6. tmp/src/app/book-monkey/iteration-4/{reactive-forms → custom-validation}/shared/book.validators.ts +30 -0
tmp/src/app/book-monkey/iteration-4/{reactive-forms → custom-validation}/book-form/book-form.component.ts RENAMED
@@ -2,6 +2,8 @@
2
import { FormBuilder, FormGroup, FormArray, Validators } from '@angular/forms';
3
4
import { Book, Thumbnail } from '../shared/book';
5
6
@Component({
7
selector: 'bm-book-form',
@@ -16,7 +18,10 @@
16
@Input() editing = false;
17
@Output() submitBook = new EventEmitter<Book>();
18
19
- constructor(private fb: FormBuilder) { }
20
21
ngOnInit() {
22
this.initForm();
@@ -47,11 +52,14 @@
47
this.bookForm = this.fb.group({
48
title: ['', Validators.required],
49
subtitle: [''],
50
- isbn: [{ value: '', disabled: this.editing }, [
51
- Validators.required,
52
- Validators.minLength(10),
53
- Validators.maxLength(13)
54
- ]],
55
description: [''],
56
authors: this.buildAuthorsArray(['']),
57
thumbnails: this.buildThumbnailsArray([
@@ -62,7 +70,7 @@
62
}
63
64
private buildAuthorsArray(values: string[]): FormArray {
65
- return this.fb.array(values, Validators.required);
66
}
67
68
private buildThumbnailsArray(values: Thumbnail[]): FormArray {
2
import { FormBuilder, FormGroup, FormArray, Validators } from '@angular/forms';
3
4
import { Book, Thumbnail } from '../shared/book';
5
+ import { BookValidators } from '../shared/book.validators';
6
+ import { BookExistsValidatorService } from '../shared/book-exists-validator.service';
7
8
@Component({
9
selector: 'bm-book-form',
18
@Input() editing = false;
19
@Output() submitBook = new EventEmitter<Book>();
20
21
+ constructor(
22
+ private fb: FormBuilder,
23
+ private bookExistsValidator: BookExistsValidatorService
24
+ ) { }
25
26
ngOnInit() {
27
this.initForm();
52
this.bookForm = this.fb.group({
53
title: ['', Validators.required],
54
subtitle: [''],
55
+ isbn: [
56
+ { value: '', disabled: this.editing },
57
+ [
58
+ Validators.required,
59
+ BookValidators.isbnFormat
60
+ ],
61
+ this.editing ? null : [this.bookExistsValidator]
62
+ ],
63
description: [''],
64
authors: this.buildAuthorsArray(['']),
65
thumbnails: this.buildThumbnailsArray([
70
}
71
72
private buildAuthorsArray(values: string[]): FormArray {
73
+ return this.fb.array(values, BookValidators.atLeastOneAuthor);
74
}
75
76
private buildThumbnailsArray(values: Thumbnail[]): FormArray {
tmp/src/app/book-monkey/iteration-4/{reactive-forms → custom-validation}/create-book/create-book.component.ts RENAMED
@@ -1,6 +1,5 @@
1
import { Component, OnInit } from '@angular/core';
2
import { ActivatedRoute, Router } from '@angular/router';
3
- import { map, switchMap } from 'rxjs/operators';
4
5
import { Book } from '../shared/book';
6
import { BookStoreService } from '../shared/book-store.service';
1
import { Component, OnInit } from '@angular/core';
2
import { ActivatedRoute, Router } from '@angular/router';
3
4
import { Book } from '../shared/book';
5
import { BookStoreService } from '../shared/book-store.service';
tmp/src/app/book-monkey/iteration-4/{reactive-forms → custom-validation}/form-messages/form-messages.component.ts RENAMED
@@ -17,14 +17,14 @@
17
},
18
isbn: {
19
required: 'Es muss eine ISBN angegeben werden.',
20
- minlength: 'Die ISBN muss mindestens 10 Zeichen haben.',
21
- maxlength: 'Die ISBN darf höchstens 13 Zeichen haben.'
22
},
23
published: {
24
required: 'Es muss ein Erscheinungsdatum angegeben werden.'
25
},
26
authors: {
27
- required: 'Es muss ein Autor angegeben werden.'
28
}
29
};
30
17
},
18
isbn: {
19
required: 'Es muss eine ISBN angegeben werden.',
20
+ isbnFormat: 'Die ISBN muss aus 10 oder 13 Zeichen bestehen.',
21
+ isbnExists: 'Die ISBN existiert bereits.'
22
},
23
published: {
24
required: 'Es muss ein Erscheinungsdatum angegeben werden.'
25
},
26
authors: {
27
+ atLeastOneAuthor: 'Es muss ein Autor angegeben werden.'
28
}
29
};
30
tmp/src/app/book-monkey/iteration-4/{reactive-forms → custom-validation}/shared/book-exists-validator.service.ts RENAMED
@@ -0,0 +1,25 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { FormControl, AsyncValidator, ValidationErrors } from '@angular/forms';
3
+ import { Observable, of } from 'rxjs';
4
+ import { map, catchError } from 'rxjs/operators';
5
+
6
+ import { BookStoreService } from './book-store.service';
7
+
8
+ @Injectable({
9
+ providedIn: 'root'
10
+ })
11
+ export class BookExistsValidatorService implements AsyncValidator {
12
+
13
+ constructor(private bs: BookStoreService) { }
14
+
15
+ validate(
16
+ control: FormControl
17
+ ): Observable<ValidationErrors | null> {
18
+ return this.bs.check(control.value).pipe(
19
+ map(exists => (exists === false) ? null : {
20
+ isbnExists: { valid: false }
21
+ }),
22
+ catchError(() => of(null))
23
+ );
24
+ }
25
+ }
tmp/src/app/book-monkey/iteration-4/{reactive-forms → custom-validation}/shared/book-store.service.ts RENAMED
@@ -77,6 +77,14 @@
77
);
78
}
79
80
private errorHandler(error: HttpErrorResponse): Observable<any> {
81
console.error('Fehler aufgetreten!');
82
return throwError(error);
77
);
78
}
79
80
+ check(isbn: string): Observable<boolean> {
81
+ return this.http.get(
82
+ `${this.api}/book/${isbn}/check`
83
+ ).pipe(
84
+ catchError(this.errorHandler)
85
+ );
86
+ }
87
+
88
private errorHandler(error: HttpErrorResponse): Observable<any> {
89
console.error('Fehler aufgetreten!');
90
return throwError(error);
tmp/src/app/book-monkey/iteration-4/{reactive-forms → custom-validation}/shared/book.validators.ts RENAMED
@@ -0,0 +1,30 @@
1
+ import { FormControl, FormArray, ValidationErrors } from '@angular/forms';
2
+
3
+ export class BookValidators {
4
+
5
+ static isbnFormat(control: FormControl): ValidationErrors | null {
6
+ if (!control.value) { return null; }
7
+
8
+ const numbers = control.value.replace(/-/g, '');
9
+ const isbnPattern = /(^\d{10}$)|(^\d{13}$)/;
10
+
11
+ if (isbnPattern.test(numbers)) {
12
+ return null;
13
+ } else {
14
+ return {
15
+ isbnFormat: { valid: false }
16
+ };
17
+ }
18
+ }
19
+
20
+ static atLeastOneAuthor(controlArray: FormArray): ValidationErrors | null {
21
+ if (controlArray.controls.some(el => el.value)) {
22
+ return null;
23
+ } else {
24
+ return {
25
+ atLeastOneAuthor: { valid: false }
26
+ };
27
+ }
28
+ }
29
+
30
+ }