Differenzansicht 13-search
im Vergleich zu 12-validation

Zurück zur Übersicht | ← Vorherige | Nächste → | Demo | Quelltext auf GitHub
src/app/books-portal/books-overview-page/books-overview-page.html CHANGED
@@ -24,7 +24,7 @@
24
  aria-label="Search"
25
  />
26
 
27
- @for (b of filteredBooks(); track b.isbn) {
28
  <app-book-card [book]="b" (like)="addLikedBook($event)" />
29
  }
30
  </div>
 
24
  aria-label="Search"
25
  />
26
 
27
+ @for (b of books.value(); track b.isbn) {
28
  <app-book-card [book]="b" (like)="addLikedBook($event)" />
29
  }
30
  </div>
src/app/books-portal/books-overview-page/books-overview-page.ts CHANGED
@@ -1,5 +1,6 @@
1
- import { Component, computed, inject, signal } from '@angular/core';
2
  import { Field, form } from '@angular/forms/signals';
 
3
 
4
  import { Book } from '../../shared/book';
5
  import { BookCard } from '../book-card/book-card';
@@ -13,25 +14,24 @@ import { BookStore } from '../../shared/book-store';
13
  })
14
  export class BooksOverviewPage {
15
  #bookStore = inject(BookStore);
 
16
 
17
- protected searchTerm = signal('');
 
18
  protected searchField = form(this.searchTerm);
19
 
20
- protected books = this.#bookStore.getAll();
21
  protected likedBooks = signal<Book[]>([]);
22
 
23
- protected filteredBooks = computed(() => {
24
- if (!this.books.hasValue()) {
25
- return [];
26
- }
27
-
28
- if (!this.searchTerm()) {
29
- return this.books.value();
30
- }
31
-
32
- const term = this.searchTerm().toLowerCase();
33
- return this.books.value().filter((b) => b.title.toLowerCase().includes(term));
34
- });
35
 
36
  addLikedBook(newLikedBook: Book) {
37
  const foundBook = this.likedBooks().find(
 
1
+ import { Component, effect, inject, input, linkedSignal, signal } from '@angular/core';
2
  import { Field, form } from '@angular/forms/signals';
3
+ import { Router } from '@angular/router';
4
 
5
  import { Book } from '../../shared/book';
6
  import { BookCard } from '../book-card/book-card';
 
14
  })
15
  export class BooksOverviewPage {
16
  #bookStore = inject(BookStore);
17
+ #router = inject(Router);
18
 
19
+ readonly search = input<string>();
20
+ protected searchTerm = linkedSignal(() => this.search() || '');
21
  protected searchField = form(this.searchTerm);
22
 
23
+ protected books = this.#bookStore.getAll(this.searchTerm);
24
  protected likedBooks = signal<Book[]>([]);
25
 
26
+ constructor() {
27
+ effect(() => {
28
+ this.#router.navigate([], {
29
+ queryParams: {
30
+ search: this.searchTerm() || null
31
+ }
32
+ });
33
+ });
34
+ }
 
 
 
35
 
36
  addLikedBook(newLikedBook: Book) {
37
  const foundBook = this.likedBooks().find(
src/app/shared/book-store.ts CHANGED
@@ -11,9 +11,12 @@ export class BookStore {
11
  #http = inject(HttpClient);
12
  #apiUrl = 'https://api6.angular-buch.com';
13
 
14
- getAll(): HttpResourceRef<Book[]> {
15
  return httpResource<Book[]>(
16
- () => `${this.#apiUrl}/books`,
 
 
 
17
  { defaultValue: [] }
18
  );
19
  }
 
11
  #http = inject(HttpClient);
12
  #apiUrl = 'https://api6.angular-buch.com';
13
 
14
+ getAll(searchTerm: Signal<string>): HttpResourceRef<Book[]> {
15
  return httpResource<Book[]>(
16
+ () => ({
17
+ url: `${this.#apiUrl}/books`,
18
+ params: { filter: searchTerm() }
19
+ }),
20
  { defaultValue: [] }
21
  );
22
  }