Differenzansicht 15-rxjs
im Vergleich zu 14-lazyloading

← Zurück zur Übersicht | Demo | Quelltext auf GitHub
src/app/home-page/home-page.ng.html CHANGED
@@ -1 +1,25 @@
1
  <h1>Welcome to the BookMonkey!</h1>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <h1>Welcome to the BookMonkey!</h1>
2
+
3
+ <hr />
4
+
5
+ <input type="search" [formControl]="searchControl" placeholder="Search" />
6
+
7
+ @if (isLoading()) {
8
+ <span aria-busy="true">Searching ...</span>
9
+ }
10
+
11
+ @if (results().length) {
12
+ <section>
13
+ <h2>Search results</h2>
14
+ <ul>
15
+ @for (b of results(); track b.isbn) {
16
+ <li>
17
+ <a [routerLink]="['/books', 'details', b.isbn]">
18
+ {{ b.title }} ({{ b.isbn }})
19
+ </a>
20
+ </li>
21
+ }
22
+ </ul>
23
+ </section>
24
+ }
25
+
src/app/home-page/home-page.ts CHANGED
@@ -1,11 +1,32 @@
1
- import { Component } from '@angular/core';
 
 
 
 
 
 
2
 
3
  @Component({
4
  selector: 'app-home-page',
5
- imports: [],
6
  templateUrl: './home-page.ng.html',
7
  styleUrl: './home-page.scss'
8
  })
9
  export class HomePage {
 
 
 
 
10
 
 
 
 
 
 
 
 
 
 
 
 
11
  }
 
1
+ import { Component, inject, signal } from '@angular/core';
2
+ import { RouterLink } from '@angular/router';
3
+ import { FormControl, ReactiveFormsModule } from '@angular/forms';
4
+ import { toSignal } from '@angular/core/rxjs-interop';
5
+ import { filter, debounceTime, distinctUntilChanged, switchMap, tap } from 'rxjs';
6
+
7
+ import { BookStore } from '../shared/book-store';
8
 
9
  @Component({
10
  selector: 'app-home-page',
11
+ imports: [ReactiveFormsModule, RouterLink],
12
  templateUrl: './home-page.ng.html',
13
  styleUrl: './home-page.scss'
14
  })
15
  export class HomePage {
16
+ #store = inject(BookStore);
17
+
18
+ searchControl = new FormControl('', { nonNullable: true });
19
+ readonly isLoading = signal(false);
20
 
21
+ readonly results = toSignal(
22
+ this.searchControl.valueChanges.pipe(
23
+ filter(term => term.length >= 3),
24
+ debounceTime(500),
25
+ distinctUntilChanged(),
26
+ tap(() => this.isLoading.set(true)),
27
+ switchMap(term => this.#store.searchBooks(term)),
28
+ tap(() => this.isLoading.set(false)),
29
+ ),
30
+ { initialValue: [] }
31
+ );
32
  }
src/app/shared/book-store.ts CHANGED
@@ -34,4 +34,11 @@ export class BookStore {
34
  createBook(book: Book): Observable<Book> {
35
  return this.#http.post<Book>(`${this.#apiUrl}/books`, book);
36
  }
 
 
 
 
 
 
 
37
  }
 
34
  createBook(book: Book): Observable<Book> {
35
  return this.#http.post<Book>(`${this.#apiUrl}/books`, book);
36
  }
37
+
38
+ searchBooks(searchTerm: string): Observable<Book[]> {
39
+ return this.#http.get<Book[]>(
40
+ `${this.#apiUrl}/books`,
41
+ { params: { search: searchTerm } }
42
+ );
43
+ }
44
  }