diff --git a/apps/angular/1-projection/src/app/component/city-card/city-card.component.ts b/apps/angular/1-projection/src/app/component/city-card/city-card.component.ts index 8895c8c84..ac328ccf2 100644 --- a/apps/angular/1-projection/src/app/component/city-card/city-card.component.ts +++ b/apps/angular/1-projection/src/app/component/city-card/city-card.component.ts @@ -1,9 +1,47 @@ -import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { rxResource } from '@angular/core/rxjs-interop'; +import { tap } from 'rxjs'; +import { CityStore } from '../../data-access/city.store'; +import { + FakeHttpService, + randomCity, +} from '../../data-access/fake-http.service'; +import { City } from '../../model/city.model'; +import { CardComponent } from '../../ui/card/card.component'; @Component({ selector: 'app-city-card', - template: 'TODO City', - imports: [], + template: ` + + + {{ item.name }} + + + `, + imports: [CardComponent], changeDetection: ChangeDetectionStrategy.OnPush, }) -export class CityCardComponent {} +export class CityCardComponent { + private http = inject(FakeHttpService); + private store = inject(CityStore); + + cities = this.store.cities; + + fetchCities = rxResource({ + loader: () => + this.http.fetchCities$.pipe(tap((city) => this.store.addAll(city))), + }); + + addNewItem() { + this.store.addOne(randomCity()); + } + + delete(id: number) { + this.store.deleteOne(id); + } +} diff --git a/apps/angular/1-projection/src/app/component/student-card/student-card.component.ts b/apps/angular/1-projection/src/app/component/student-card/student-card.component.ts index bdfa4abd4..7bb50f1f3 100644 --- a/apps/angular/1-projection/src/app/component/student-card/student-card.component.ts +++ b/apps/angular/1-projection/src/app/component/student-card/student-card.component.ts @@ -1,12 +1,13 @@ +import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { rxResource } from '@angular/core/rxjs-interop'; +import { tap } from 'rxjs'; import { - ChangeDetectionStrategy, - Component, - inject, - OnInit, -} from '@angular/core'; -import { FakeHttpService } from '../../data-access/fake-http.service'; + FakeHttpService, + randStudent, +} from '../../data-access/fake-http.service'; import { StudentStore } from '../../data-access/student.store'; import { CardType } from '../../model/card.model'; +import { Student } from '../../model/student.model'; import { CardComponent } from '../../ui/card/card.component'; @Component({ @@ -14,27 +15,34 @@ import { CardComponent } from '../../ui/card/card.component'; template: ` `, - styles: [ - ` - ::ng-deep .bg-light-green { - background-color: rgba(0, 250, 0, 0.1); - } - `, - ], + styles: [], imports: [CardComponent], changeDetection: ChangeDetectionStrategy.OnPush, }) -export class StudentCardComponent implements OnInit { +export class StudentCardComponent { private http = inject(FakeHttpService); private store = inject(StudentStore); students = this.store.students; cardType = CardType.STUDENT; - ngOnInit(): void { - this.http.fetchStudents$.subscribe((s) => this.store.addAll(s)); + fetchStudents = rxResource({ + loader: () => + this.http.fetchStudents$.pipe( + tap((student) => this.store.addAll(student)), + ), + }); + + addNewItem() { + this.store.addOne(randStudent()); + } + + delete(id: number) { + this.store.deleteOne(id); } } diff --git a/apps/angular/1-projection/src/app/component/teacher-card/teacher-card.component.ts b/apps/angular/1-projection/src/app/component/teacher-card/teacher-card.component.ts index adf0ad3c1..a22a3792a 100644 --- a/apps/angular/1-projection/src/app/component/teacher-card/teacher-card.component.ts +++ b/apps/angular/1-projection/src/app/component/teacher-card/teacher-card.component.ts @@ -1,7 +1,12 @@ -import { Component, inject, OnInit } from '@angular/core'; -import { FakeHttpService } from '../../data-access/fake-http.service'; +import { Component, inject } from '@angular/core'; +import { rxResource } from '@angular/core/rxjs-interop'; +import { tap } from 'rxjs'; +import { + FakeHttpService, + randTeacher, +} from '../../data-access/fake-http.service'; import { TeacherStore } from '../../data-access/teacher.store'; -import { CardType } from '../../model/card.model'; +import { Teacher } from '../../model/teacher.model'; import { CardComponent } from '../../ui/card/card.component'; @Component({ @@ -9,26 +14,29 @@ import { CardComponent } from '../../ui/card/card.component'; template: ` `, - styles: [ - ` - ::ng-deep .bg-light-red { - background-color: rgba(250, 0, 0, 0.1); - } - `, - ], imports: [CardComponent], }) -export class TeacherCardComponent implements OnInit { +export class TeacherCardComponent { private http = inject(FakeHttpService); private store = inject(TeacherStore); teachers = this.store.teachers; - cardType = CardType.TEACHER; - ngOnInit(): void { - this.http.fetchTeachers$.subscribe((t) => this.store.addAll(t)); + fetchTeachers = rxResource({ + loader: () => + this.http.fetchTeachers$.pipe(tap((t) => this.store.addAll(t))), + }); + + addNewItem() { + this.store.addOne(randTeacher()); + } + + delete(id: number) { + this.store.deleteOne(id); } } diff --git a/apps/angular/1-projection/src/app/data-access/city.store.ts b/apps/angular/1-projection/src/app/data-access/city.store.ts index a8b523569..9fbcb346b 100644 --- a/apps/angular/1-projection/src/app/data-access/city.store.ts +++ b/apps/angular/1-projection/src/app/data-access/city.store.ts @@ -5,7 +5,7 @@ import { City } from '../model/city.model'; providedIn: 'root', }) export class CityStore { - private cities = signal([]); + public cities = signal([]); addAll(cities: City[]) { this.cities.set(cities); diff --git a/apps/angular/1-projection/src/app/ui/card/card.component.ts b/apps/angular/1-projection/src/app/ui/card/card.component.ts index 1a6c3648c..b1cc08ee6 100644 --- a/apps/angular/1-projection/src/app/ui/card/card.component.ts +++ b/apps/angular/1-projection/src/app/ui/card/card.component.ts @@ -1,9 +1,11 @@ -import { NgOptimizedImage } from '@angular/common'; -import { Component, inject, input } from '@angular/core'; -import { randStudent, randTeacher } from '../../data-access/fake-http.service'; -import { StudentStore } from '../../data-access/student.store'; -import { TeacherStore } from '../../data-access/teacher.store'; -import { CardType } from '../../model/card.model'; +import { NgOptimizedImage, NgTemplateOutlet } from '@angular/common'; +import { + Component, + contentChild, + input, + output, + TemplateRef, +} from '@angular/core'; import { ListItemComponent } from '../list-item/list-item.component'; @Component({ @@ -12,47 +14,38 @@ import { ListItemComponent } from '../list-item/list-item.component';
- @if (type() === CardType.TEACHER) { - - } - @if (type() === CardType.STUDENT) { - - } - +
@for (item of list(); track item) { - + + + }
+ + + {{ item.firstName }} +
`, - imports: [ListItemComponent, NgOptimizedImage], + imports: [ListItemComponent, NgOptimizedImage, NgTemplateOutlet], }) export class CardComponent { - private teacherStore = inject(TeacherStore); - private studentStore = inject(StudentStore); - readonly list = input(null); - readonly type = input.required(); + readonly cardImgSrc = input.required(); readonly customClass = input(''); - CardType = CardType; - - addNewItem() { - const type = this.type(); - if (type === CardType.TEACHER) { - this.teacherStore.addOne(randTeacher()); - } else if (type === CardType.STUDENT) { - this.studentStore.addOne(randStudent()); - } - } + nameTemplate = contentChild>('nameTemplate'); + delete = output(); + addNewItem = output(); } diff --git a/apps/angular/1-projection/src/app/ui/list-item/list-item.component.ts b/apps/angular/1-projection/src/app/ui/list-item/list-item.component.ts index cffabb451..88d8d8ba7 100644 --- a/apps/angular/1-projection/src/app/ui/list-item/list-item.component.ts +++ b/apps/angular/1-projection/src/app/ui/list-item/list-item.component.ts @@ -1,19 +1,16 @@ import { ChangeDetectionStrategy, Component, - inject, input, + output, } from '@angular/core'; -import { StudentStore } from '../../data-access/student.store'; -import { TeacherStore } from '../../data-access/teacher.store'; -import { CardType } from '../../model/card.model'; @Component({ selector: 'app-list-item', template: `
- {{ name() }} -
@@ -22,19 +19,7 @@ import { CardType } from '../../model/card.model'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class ListItemComponent { - private teacherStore = inject(TeacherStore); - private studentStore = inject(StudentStore); - readonly id = input.required(); - readonly name = input.required(); - readonly type = input.required(); - delete(id: number) { - const type = this.type(); - if (type === CardType.TEACHER) { - this.teacherStore.deleteOne(id); - } else if (type === CardType.STUDENT) { - this.studentStore.deleteOne(id); - } - } + delete = output(); } diff --git a/apps/angular/1-projection/src/styles.scss b/apps/angular/1-projection/src/styles.scss index b5c61c956..3347fc85c 100644 --- a/apps/angular/1-projection/src/styles.scss +++ b/apps/angular/1-projection/src/styles.scss @@ -1,3 +1,11 @@ @tailwind base; @tailwind components; @tailwind utilities; + +.bg-light-green { + background-color: rgba(0, 250, 0, 0.1); +} + +.bg-light-red { + background-color: rgba(250, 0, 0, 0.1); +}