Differenzansicht 01-components
im Vergleich zu 00-base

Zurück zur Übersicht | Nächste → | Demo | Quelltext auf GitHub
src/app/app.html CHANGED
@@ -1 +1,3 @@
1
- <main></main>
 
 
 
1
+ <main>
2
+ <app-books-overview-page />
3
+ </main>
src/app/app.spec.ts CHANGED
@@ -13,19 +13,4 @@ describe('App', () => {
13
  const app = fixture.componentInstance;
14
  expect(app).toBeTruthy();
15
  });
16
-
17
- /*
18
- it(`should have the 'book-manager' title`, () => {
19
- const fixture = TestBed.createComponent(App);
20
- const app = fixture.componentInstance;
21
- expect(app.title).toEqual('book-manager');
22
- });
23
-
24
- it('should render title', () => {
25
- const fixture = TestBed.createComponent(App);
26
- fixture.detectChanges();
27
- const compiled = fixture.nativeElement as HTMLElement;
28
- expect(compiled.querySelector('h1')?.textContent).toContain('Hello, book-manager');
29
- });
30
- */
31
  });
 
13
  const app = fixture.componentInstance;
14
  expect(app).toBeTruthy();
15
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  });
src/app/app.ts CHANGED
@@ -1,8 +1,10 @@
1
  import { Component } from '@angular/core';
2
 
 
 
3
  @Component({
4
  selector: 'app-root',
5
- imports: [],
6
  templateUrl: './app.html',
7
  styleUrl: './app.scss'
8
  })
 
1
  import { Component } from '@angular/core';
2
 
3
+ import { BooksOverviewPage } from './books-portal/books-overview-page/books-overview-page';
4
+
5
  @Component({
6
  selector: 'app-root',
7
+ imports: [BooksOverviewPage],
8
  templateUrl: './app.html',
9
  styleUrl: './app.scss'
10
  })
src/app/books-portal/books-overview-page/books-overview-page.html ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <section>
2
+ <h1>Books</h1>
3
+ <div>
4
+ @for (b of books(); track b.isbn) {
5
+ <article class="book-card">
6
+ <header>
7
+ <h2>{{ b.title }}</h2>
8
+ </header>
9
+ <div>
10
+ @if (b.subtitle) {
11
+ <p role="doc-subtitle">{{ b.subtitle }}</p>
12
+ }
13
+ ISBN: {{ b.isbn }}
14
+ </div>
15
+ </article>
16
+ }
17
+ </div>
18
+ </section>
src/app/books-portal/books-overview-page/books-overview-page.spec.ts ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { BooksOverviewPage } from './books-overview-page';
4
+
5
+ describe('BooksOverviewPage', () => {
6
+ let component: BooksOverviewPage;
7
+ let fixture: ComponentFixture<BooksOverviewPage>;
8
+
9
+ // Arrange
10
+ beforeEach(async () => {
11
+ await TestBed.configureTestingModule({
12
+ imports: [BooksOverviewPage]
13
+ })
14
+ .compileComponents();
15
+
16
+ fixture = TestBed.createComponent(BooksOverviewPage);
17
+ component = fixture.componentInstance;
18
+ });
19
+
20
+ it('should have a list of 2 books', () => {
21
+ // Act
22
+ // Daten aus Signal auslesen, dieses wird bereits im Konstruktor gesetzt
23
+ const books = component['books']();
24
+
25
+ // Assert
26
+ expect(books.length).toBe(2);
27
+ expect(books[0].title).toContain('Tierisch gut kochen');
28
+ expect(books[1].title).toContain('Backen mit Affen');
29
+ });
30
+
31
+ it('should render the correct book titles', () => {
32
+ // Act
33
+ // Durch detectChanges() wird das Template "gerendert"
34
+ fixture.detectChanges();
35
+
36
+ // Im gerenderten DOM nach dem Tag <article> suchen
37
+ const compiledElement: HTMLElement = fixture.nativeElement;
38
+ const articleEls = compiledElement.querySelectorAll('article');
39
+
40
+ // Assert
41
+ expect(articleEls.length).toBe(2);
42
+ expect(articleEls[0].textContent).toContain('Tierisch gut kochen');
43
+ expect(articleEls[1].textContent).toContain('Backen mit Affen');
44
+ });
45
+ });
src/app/books-portal/books-overview-page/books-overview-page.ts ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Component, signal } from '@angular/core';
2
+
3
+ import { Book } from '../../shared/book';
4
+
5
+ @Component({
6
+ selector: 'app-books-overview-page',
7
+ imports: [],
8
+ templateUrl: './books-overview-page.html',
9
+ styleUrl: './books-overview-page.scss',
10
+ })
11
+ export class BooksOverviewPage {
12
+ protected books = signal<Book[]>([]);
13
+
14
+ constructor() {
15
+ this.books.set([
16
+ {
17
+ isbn: '12345',
18
+ title: 'Tierisch gut kochen',
19
+ authors: ['Mrs Chimp', 'Mr Gorilla'],
20
+ subtitle: 'Rezepte von Affe bis Zebra',
21
+ imageUrl: 'https://cdn.ng-buch.de/kochen.png',
22
+ description: 'Immer lecker und gut',
23
+ createdAt: new Date().toISOString(),
24
+ },
25
+ {
26
+ isbn: '67890',
27
+ title: 'Backen mit Affen',
28
+ subtitle: 'Bananenbrot und mehr',
29
+ authors: ['Orang Utan'],
30
+ imageUrl: 'https://cdn.ng-buch.de/backen.png',
31
+ description: 'Tolle Backtipps für Mensch und Tier',
32
+ createdAt: new Date().toISOString(),
33
+ },
34
+ ]);
35
+ }
36
+ }
src/app/shared/book.ts ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ export interface Book {
2
+ isbn: string;
3
+ title: string;
4
+ subtitle?: string;
5
+ authors: string[];
6
+ description: string;
7
+ imageUrl: string;
8
+ createdAt: string;
9
+ }