Skip to content

Answer:1 #1313

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,9 +1,48 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { NgOptimizedImage } from '@angular/common';
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
import { CityStore } from '../../data-access/city.store';
import { randomCity } from '../../data-access/fake-http.service';
import { CardType } from '../../model/card.model';
import { CardComponent } from '../../ui/card/card.component';

@Component({
selector: 'app-city-card',
template: 'TODO City',
imports: [],
template: `
<app-card
[list]="cities()"
[type]="cardType"
(addNewItem)="addCity()"
(delete)="deleteCity($event)"
class="bg-light-blue">
<img
ngSrc="assets/img/city.png"
width="200"
height="200"
priority
ngProjectAs="card-img" />
</app-card>
`,
styles: [
`
.bg-light-blue {
background-color: rgba(0, 171, 250, 0.1);
}
`,
],
imports: [CardComponent, NgOptimizedImage],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CityCardComponent {}
export class CityCardComponent {
private store = inject(CityStore);

readonly cities = this.store.cities;
readonly cardType = CardType.CITY;

addCity() {
this.store.addOne(randomCity());
}

deleteCity(id: number) {
this.store.deleteOne(id);
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import {
ChangeDetectionStrategy,
Component,
inject,
OnInit,
} from '@angular/core';
import { FakeHttpService } from '../../data-access/fake-http.service';
import { NgOptimizedImage } from '@angular/common';
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
import { randStudent } from '../../data-access/fake-http.service';
import { StudentStore } from '../../data-access/student.store';
import { CardType } from '../../model/card.model';
import { CardComponent } from '../../ui/card/card.component';
Expand All @@ -15,26 +11,38 @@ import { CardComponent } from '../../ui/card/card.component';
<app-card
[list]="students()"
[type]="cardType"
customClass="bg-light-green" />
(addNewItem)="addStudent()"
(delete)="deleteStudent($event)"
class="bg-light-green">
<img
ngSrc="assets/img/student.webp"
width="200"
height="200"
priority
ngProjectAs="card-img" />
</app-card>
`,
styles: [
`
::ng-deep .bg-light-green {
.bg-light-green {
background-color: rgba(0, 250, 0, 0.1);
}
`,
],
imports: [CardComponent],
imports: [CardComponent, NgOptimizedImage],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class StudentCardComponent implements OnInit {
private http = inject(FakeHttpService);
export class StudentCardComponent {
private store = inject(StudentStore);

students = this.store.students;
cardType = CardType.STUDENT;
readonly students = this.store.students;
readonly cardType = CardType.STUDENT;

ngOnInit(): void {
this.http.fetchStudents$.subscribe((s) => this.store.addAll(s));
addStudent() {
this.store.addOne(randStudent());
}

deleteStudent(id: number) {
this.store.deleteOne(id);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Component, inject, OnInit } from '@angular/core';
import { FakeHttpService } from '../../data-access/fake-http.service';
import { NgOptimizedImage } from '@angular/common';
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
import { randTeacher } from '../../data-access/fake-http.service';
import { TeacherStore } from '../../data-access/teacher.store';
import { CardType } from '../../model/card.model';
import { CardComponent } from '../../ui/card/card.component';
Expand All @@ -10,25 +11,38 @@ import { CardComponent } from '../../ui/card/card.component';
<app-card
[list]="teachers()"
[type]="cardType"
customClass="bg-light-red"></app-card>
(addNewItem)="addTeacher()"
(delete)="deleteTeacher($event)"
class="bg-light-red">
<img
ngSrc="assets/img/teacher.png"
width="200"
height="200"
priority
ngProjectAs="card-img" />
</app-card>
`,
styles: [
`
::ng-deep .bg-light-red {
.bg-light-red {
background-color: rgba(250, 0, 0, 0.1);
}
`,
],
imports: [CardComponent],
imports: [CardComponent, NgOptimizedImage],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class TeacherCardComponent implements OnInit {
private http = inject(FakeHttpService);
export class TeacherCardComponent {
private store = inject(TeacherStore);

teachers = this.store.teachers;
cardType = CardType.TEACHER;
readonly teachers = this.store.teachers;
readonly cardType = CardType.TEACHER;

ngOnInit(): void {
this.http.fetchTeachers$.subscribe((t) => this.store.addAll(t));
addTeacher() {
this.store.addOne(randTeacher());
}

deleteTeacher(id: number) {
this.store.deleteOne(id);
}
}
12 changes: 10 additions & 2 deletions apps/angular/1-projection/src/app/data-access/city.store.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import { Injectable, signal } from '@angular/core';
import { effect, inject, Injectable, signal } from '@angular/core';
import { City } from '../model/city.model';
import { FakeHttpService } from './fake-http.service';

@Injectable({
providedIn: 'root',
})
export class CityStore {
private cities = signal<City[]>([]);
private readonly http = inject(FakeHttpService);
public cities = signal<City[]>([]);

constructor() {
effect(() => {
this.http.fetchCities$.subscribe((c) => this.addAll(c));
});
}

addAll(cities: City[]) {
this.cities.set(cities);
Expand Down
10 changes: 9 additions & 1 deletion apps/angular/1-projection/src/app/data-access/student.store.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
import { Injectable, signal } from '@angular/core';
import { effect, inject, Injectable, signal } from '@angular/core';
import { Student } from '../model/student.model';
import { FakeHttpService } from './fake-http.service';

@Injectable({
providedIn: 'root',
})
export class StudentStore {
private readonly http = inject(FakeHttpService);
public students = signal<Student[]>([]);

constructor() {
effect(() => {
this.http.fetchStudents$.subscribe((s) => this.addAll(s));
});
}

addAll(students: Student[]) {
this.students.set(students);
}
Expand Down
12 changes: 10 additions & 2 deletions apps/angular/1-projection/src/app/data-access/teacher.store.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import { Injectable, signal } from '@angular/core';
import { effect, inject, Injectable, signal } from '@angular/core';
import { Teacher } from '../model/teacher.model';
import { FakeHttpService } from './fake-http.service';

@Injectable({
providedIn: 'root',
})
export class TeacherStore {
public teachers = signal<Teacher[]>([]);
private readonly http = inject(FakeHttpService);
readonly teachers = signal<Teacher[]>([]);

constructor() {
effect(() => {
this.http.fetchTeachers$.subscribe((t) => this.addAll(t));
});
}

addAll(teachers: Teacher[]) {
this.teachers.set(teachers);
Expand Down
75 changes: 34 additions & 41 deletions apps/angular/1-projection/src/app/ui/card/card.component.ts
Original file line number Diff line number Diff line change
@@ -1,58 +1,51 @@
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 {
ChangeDetectionStrategy,
Component,
input,
output,
} from '@angular/core';
import { CardType } from '../../model/card.model';
import { ListItemComponent } from '../list-item/list-item.component';

@Component({
selector: 'app-card',
template: `
<div
class="flex w-fit flex-col gap-3 rounded-md border-2 border-black p-4"
[class]="customClass()">
@if (type() === CardType.TEACHER) {
<img ngSrc="assets/img/teacher.png" width="200" height="200" />
}
@if (type() === CardType.STUDENT) {
<img ngSrc="assets/img/student.webp" width="200" height="200" />
}
<ng-content select="card-img"></ng-content>

<section>
@for (item of list(); track item) {
<app-list-item
[name]="item.firstName"
[id]="item.id"
[type]="type()"></app-list-item>
}
</section>
<section>
@for (item of list(); track item) {
<app-list-item
[item]="item"
[type]="type()"
(deleteItem)="handleDelete($event)"></app-list-item>
}
</section>

<button
class="rounded-sm border border-blue-500 bg-blue-300 p-2"
(click)="addNewItem()">
Add
</button>
</div>
<button
class="rounded-sm border border-blue-500 bg-blue-300 p-2"
(click)="onAdd()"
ngProjectAs="card-add-btn">
Add
</button>
`,
imports: [ListItemComponent, NgOptimizedImage],
host: {
class: 'flex w-fit flex-col gap-3 rounded-md border-2 border-black p-4',
},
imports: [ListItemComponent],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CardComponent {
private teacherStore = inject(TeacherStore);
private studentStore = inject(StudentStore);

readonly list = input<any[] | null>(null);
readonly type = input.required<CardType>();
readonly customClass = input('');

CardType = CardType;
readonly addNewItem = output<any>();
readonly delete = output<number>();

onAdd() {
this.addNewItem.emit('');
}

addNewItem() {
const type = this.type();
if (type === CardType.TEACHER) {
this.teacherStore.addOne(randTeacher());
} else if (type === CardType.STUDENT) {
this.studentStore.addOne(randStudent());
}
handleDelete(id: number) {
this.delete.emit(id);
}
}
Original file line number Diff line number Diff line change
@@ -1,40 +1,36 @@
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: `
<div class="border-grey-300 flex justify-between border px-2 py-1">
{{ name() }}
<button (click)="delete(id())">
<img class="h-5" src="assets/svg/trash.svg" />
</button>
</div>
@if (type() === CardType.TEACHER || type() === CardType.STUDENT) {
{{ item().firstName }}
} @else if (type() === CardType.CITY) {
{{ item().name }}
}

<button (click)="onDelete(item().id)">
<img class="h-5" src="assets/svg/trash.svg" />
</button>
`,
standalone: true,
host: { class: 'border-grey-300 flex justify-between border px-2 py-1' },
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ListItemComponent {
private teacherStore = inject(TeacherStore);
private studentStore = inject(StudentStore);

readonly id = input.required<number>();
readonly name = input.required<string>();
readonly item = input.required<any>();
readonly type = input.required<CardType>();

delete(id: number) {
const type = this.type();
if (type === CardType.TEACHER) {
this.teacherStore.deleteOne(id);
} else if (type === CardType.STUDENT) {
this.studentStore.deleteOne(id);
}
readonly deleteItem = output<number>();

CardType = CardType;

onDelete(id: number) {
this.deleteItem.emit(id);
}
}