diff --git a/README.md b/README.md
index 0e2071ecf..8a9042a02 100644
--- a/README.md
+++ b/README.md
@@ -5,6 +5,7 @@
Collection of Angular challenges
+adsfsadfasd
## Intro
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 47b089650..45a9c5e0b 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,12 +1,54 @@
-import { Component, OnInit } from '@angular/core';
+import { Component, OnInit, computed, inject } from '@angular/core';
+import { CityStore } from '../../data-access/city.store';
+import {
+ FakeHttpService,
+ randomCity,
+} from '../../data-access/fake-http.service';
+import { CardListItem } from '../../model/card.model';
+import { CardComponent } from '../../ui/card/card.component';
@Component({
selector: 'app-city-card',
- template: 'TODO City',
- imports: [],
+ template: `
+
+
+

+
+
+ `,
+ styles: [
+ `
+ .bg-light-green {
+ background-color: rgba(0, 250, 0, 0.1);
+ }
+ `,
+ ],
+ imports: [CardComponent],
})
export class CityCardComponent implements OnInit {
- constructor() {}
+ private http = inject(FakeHttpService);
+ private store = inject(CityStore);
- ngOnInit(): void {}
+ cityListItems = computed(() =>
+ this.store.cities().map((city) => ({
+ name: city.name,
+ id: city.id,
+ })),
+ );
+
+ ngOnInit(): void {
+ this.http.fetchCities$.subscribe((e) => this.store.addAll(e));
+ }
+
+ handleAddNewItemEvent() {
+ this.store.addOne(randomCity());
+ }
+
+ handleDeleteItemEvent(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 dae48a2d5..748f50587 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,21 +1,28 @@
-import { Component, OnInit } from '@angular/core';
-import { FakeHttpService } from '../../data-access/fake-http.service';
+import { Component, OnInit, computed, inject } from '@angular/core';
+import {
+ 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 { CardListItem } from '../../model/card.model';
import { CardComponent } from '../../ui/card/card.component';
@Component({
selector: 'app-student-card',
template: `
+ [list]="studentListItems()"
+ class="bg-light-green"
+ (addNewItemEvent)="handleAddNewItemEvent()"
+ (deleteItemEvent)="handleDeleteItemEvent($event)">
+
+

+
+
`,
styles: [
`
- ::ng-deep .bg-light-green {
+ .bg-light-green {
background-color: rgba(0, 250, 0, 0.1);
}
`,
@@ -23,17 +30,27 @@ import { CardComponent } from '../../ui/card/card.component';
imports: [CardComponent],
})
export class StudentCardComponent implements OnInit {
- students: Student[] = [];
- cardType = CardType.STUDENT;
+ private http = inject(FakeHttpService);
+ private store = inject(StudentStore);
- constructor(
- private http: FakeHttpService,
- private store: StudentStore,
- ) {}
+ students = this.store.students;
+
+ studentListItems = computed(() =>
+ this.store.students().map((student) => ({
+ name: student.firstName,
+ id: student.id,
+ })),
+ );
ngOnInit(): void {
this.http.fetchStudents$.subscribe((s) => this.store.addAll(s));
+ }
+
+ handleAddNewItemEvent() {
+ this.store.addOne(randStudent());
+ }
- this.store.students$.subscribe((s) => (this.students = s));
+ handleDeleteItemEvent(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 815cde9d5..049137ee7 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,21 +1,28 @@
-import { Component, OnInit } from '@angular/core';
-import { FakeHttpService } from '../../data-access/fake-http.service';
+import { Component, OnInit, computed, inject } from '@angular/core';
+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 { CardListItem } from '../../model/card.model';
import { CardComponent } from '../../ui/card/card.component';
@Component({
selector: 'app-teacher-card',
template: `
+ [list]="teacherListItems()"
+ class="bg-light-red"
+ (addNewItemEvent)="handleAddNewItemEvent()"
+ (deleteItemEvent)="handleDeleteItemEvent($event)">
+
+

+
+
`,
styles: [
`
- ::ng-deep .bg-light-red {
+ .bg-light-red {
background-color: rgba(250, 0, 0, 0.1);
}
`,
@@ -23,17 +30,24 @@ import { CardComponent } from '../../ui/card/card.component';
imports: [CardComponent],
})
export class TeacherCardComponent implements OnInit {
- teachers: Teacher[] = [];
- cardType = CardType.TEACHER;
+ private http = inject(FakeHttpService);
+ private store = inject(TeacherStore);
- constructor(
- private http: FakeHttpService,
- private store: TeacherStore,
- ) {}
+ teacherListItems = computed(() =>
+ this.store
+ .teachers()
+ .map((teacher) => ({ name: teacher.firstName, id: teacher.id })),
+ );
ngOnInit(): void {
this.http.fetchTeachers$.subscribe((t) => this.store.addAll(t));
+ }
+
+ handleAddNewItemEvent() {
+ this.store.addOne(randTeacher());
+ }
- this.store.teachers$.subscribe((t) => (this.teachers = t));
+ handleDeleteItemEvent(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 711dad1d7..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
@@ -1,23 +1,21 @@
-import { Injectable } from '@angular/core';
-import { BehaviorSubject } from 'rxjs';
+import { Injectable, signal } from '@angular/core';
import { City } from '../model/city.model';
@Injectable({
providedIn: 'root',
})
export class CityStore {
- private cities = new BehaviorSubject([]);
- cities$ = this.cities.asObservable();
+ public cities = signal([]);
addAll(cities: City[]) {
- this.cities.next(cities);
+ this.cities.set(cities);
}
- addOne(student: City) {
- this.cities.next([...this.cities.value, student]);
+ addOne(city: City) {
+ this.cities.set([...this.cities(), city]);
}
deleteOne(id: number) {
- this.cities.next(this.cities.value.filter((s) => s.id !== id));
+ this.cities.set(this.cities().filter((s) => s.id !== id));
}
}
diff --git a/apps/angular/1-projection/src/app/data-access/student.store.ts b/apps/angular/1-projection/src/app/data-access/student.store.ts
index 7918118c3..6e7f57022 100644
--- a/apps/angular/1-projection/src/app/data-access/student.store.ts
+++ b/apps/angular/1-projection/src/app/data-access/student.store.ts
@@ -1,23 +1,21 @@
-import { Injectable } from '@angular/core';
-import { BehaviorSubject } from 'rxjs';
+import { Injectable, signal } from '@angular/core';
import { Student } from '../model/student.model';
@Injectable({
providedIn: 'root',
})
export class StudentStore {
- private students = new BehaviorSubject([]);
- students$ = this.students.asObservable();
+ public students = signal([]);
addAll(students: Student[]) {
- this.students.next(students);
+ this.students.set(students);
}
addOne(student: Student) {
- this.students.next([...this.students.value, student]);
+ this.students.set([...this.students(), student]);
}
deleteOne(id: number) {
- this.students.next(this.students.value.filter((s) => s.id !== id));
+ this.students.set(this.students().filter((s) => s.id !== id));
}
}
diff --git a/apps/angular/1-projection/src/app/data-access/teacher.store.ts b/apps/angular/1-projection/src/app/data-access/teacher.store.ts
index 93f68c4b1..5f6dae989 100644
--- a/apps/angular/1-projection/src/app/data-access/teacher.store.ts
+++ b/apps/angular/1-projection/src/app/data-access/teacher.store.ts
@@ -1,23 +1,21 @@
-import { Injectable } from '@angular/core';
-import { BehaviorSubject } from 'rxjs';
+import { Injectable, signal } from '@angular/core';
import { Teacher } from '../model/teacher.model';
@Injectable({
providedIn: 'root',
})
export class TeacherStore {
- private teachers = new BehaviorSubject([]);
- teachers$ = this.teachers.asObservable();
+ public teachers = signal([]);
addAll(teachers: Teacher[]) {
- this.teachers.next(teachers);
+ this.teachers.set(teachers);
}
addOne(teacher: Teacher) {
- this.teachers.next([...this.teachers.value, teacher]);
+ this.teachers.set([...this.teachers(), teacher]);
}
deleteOne(id: number) {
- this.teachers.next(this.teachers.value.filter((t) => t.id !== id));
+ this.teachers.set(this.teachers().filter((t) => t.id !== id));
}
}
diff --git a/apps/angular/1-projection/src/app/model/card.model.ts b/apps/angular/1-projection/src/app/model/card.model.ts
index 740cd2ae4..69c0e7d17 100644
--- a/apps/angular/1-projection/src/app/model/card.model.ts
+++ b/apps/angular/1-projection/src/app/model/card.model.ts
@@ -3,3 +3,8 @@ export enum CardType {
STUDENT,
CITY,
}
+
+export interface CardListItem {
+ name: string;
+ id: number;
+}
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 ca3c661de..2665e70c3 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,60 +1,39 @@
-import { NgFor, NgIf } from '@angular/common';
-import { Component, 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 { Component, input, output } from '@angular/core';
+import { CardListItem } from '../../model/card.model';
import { ListItemComponent } from '../list-item/list-item.component';
@Component({
selector: 'app-card',
template: `
-
-

-

-
-
+
+
+ @for (item of list(); track $index) {
-
-
-
-
+ (deleteItemEvent)="handleDeleteItemEvent($event)" />
+ }
+
+
`,
- imports: [NgIf, NgFor, ListItemComponent],
+ imports: [ListItemComponent],
+ host: {
+ class: 'border-2 border-black rounded-md p-4 w-fit flex flex-col gap-3',
+ },
})
export class CardComponent {
- @Input() list: any[] | null = null;
- @Input() type!: CardType;
- @Input() customClass = '';
-
- CardType = CardType;
-
- constructor(
- private teacherStore: TeacherStore,
- private studentStore: StudentStore,
- ) {}
+ list = input([]);
+ deleteItemEvent = output();
+ addNewItemEvent = output();
addNewItem() {
- if (this.type === CardType.TEACHER) {
- this.teacherStore.addOne(randTeacher());
- } else if (this.type === CardType.STUDENT) {
- this.studentStore.addOne(randStudent());
- }
+ this.addNewItemEvent.emit();
+ }
+ handleDeleteItemEvent(id: number) {
+ this.deleteItemEvent.emit(id);
}
}
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 c0f9cff7f..f5511d59e 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,14 +1,11 @@
-import { Component, Input } from '@angular/core';
-import { StudentStore } from '../../data-access/student.store';
-import { TeacherStore } from '../../data-access/teacher.store';
-import { CardType } from '../../model/card.model';
+import { Component, input, output } from '@angular/core';
@Component({
selector: 'app-list-item',
template: `
- {{ name }}
-
@@ -16,20 +13,11 @@ import { CardType } from '../../model/card.model';
standalone: true,
})
export class ListItemComponent {
- @Input() id!: number;
- @Input() name!: string;
- @Input() type!: CardType;
-
- constructor(
- private teacherStore: TeacherStore,
- private studentStore: StudentStore,
- ) {}
+ id = input.required();
+ name = input.required();
+ deleteItemEvent = output();
delete(id: number) {
- if (this.type === CardType.TEACHER) {
- this.teacherStore.deleteOne(id);
- } else if (this.type === CardType.STUDENT) {
- this.studentStore.deleteOne(id);
- }
+ this.deleteItemEvent.emit(id);
}
}
diff --git a/package-lock.json b/package-lock.json
index c3d9e6ed8..4797f709c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -90,7 +90,7 @@
"jsonc-eslint-parser": "^2.1.0",
"lint-staged": "^13.0.3",
"ng-packagr": "19.0.1",
- "nx": "20.2.0",
+ "nx": "^20.2.0",
"postcss": "^8.4.5",
"postcss-import": "~14.1.0",
"postcss-preset-env": "~7.5.0",
diff --git a/package.json b/package.json
index 1db96f21f..27a3f7d1b 100644
--- a/package.json
+++ b/package.json
@@ -93,7 +93,7 @@
"jsonc-eslint-parser": "^2.1.0",
"lint-staged": "^13.0.3",
"ng-packagr": "19.0.1",
- "nx": "20.2.0",
+ "nx": "^20.2.0",
"postcss": "^8.4.5",
"postcss-import": "~14.1.0",
"postcss-preset-env": "~7.5.0",