From 705da0320c978ea9147aaee9c8d49c8fb5a53c68 Mon Sep 17 00:00:00 2001 From: michal Date: Wed, 20 Mar 2024 16:14:47 +0100 Subject: [PATCH 1/6] finish task projection ! --- .../city-card/city-card.component.ts | 35 ++++++++++++++++--- .../src/app/ui/card/card.component.ts | 17 +++++++-- .../app/ui/list-item/list-item.component.ts | 4 +++ 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/apps/angular/projection/src/app/component/city-card/city-card.component.ts b/apps/angular/projection/src/app/component/city-card/city-card.component.ts index 30c8f88ec..22612eb10 100644 --- a/apps/angular/projection/src/app/component/city-card/city-card.component.ts +++ b/apps/angular/projection/src/app/component/city-card/city-card.component.ts @@ -1,13 +1,40 @@ import { Component, OnInit } from '@angular/core'; +import { CityStore } from '../../data-access/city.store'; +import { FakeHttpService } from '../../data-access/fake-http.service'; +import { CardType } from '../../model/card.model'; +import { City } from '../../model/city.model'; +import { CardComponent } from '../../ui/card/card.component'; @Component({ selector: 'app-city-card', - template: 'TODO City', + template: ` + + `, + styles: [ + ` + ::ng-deep .bg-light-red { + background-color: rgba(250, 0, 0, 0.1); + } + `, + ], standalone: true, - imports: [], + imports: [CardComponent], }) export class CityCardComponent implements OnInit { - constructor() {} + cities: City[] = []; + cardType = CardType.CITY; - ngOnInit(): void {} + constructor( + private http: FakeHttpService, + private store: CityStore, + ) {} + + ngOnInit(): void { + this.http.fetchCities$.subscribe((s) => this.store.addAll(s)); + + this.store.cities$.subscribe((s) => (this.cities = s)); + } } diff --git a/apps/angular/projection/src/app/ui/card/card.component.ts b/apps/angular/projection/src/app/ui/card/card.component.ts index f06c9ae00..417757cc5 100644 --- a/apps/angular/projection/src/app/ui/card/card.component.ts +++ b/apps/angular/projection/src/app/ui/card/card.component.ts @@ -1,6 +1,11 @@ import { NgFor, NgIf } from '@angular/common'; import { Component, Input } from '@angular/core'; -import { randStudent, randTeacher } from '../../data-access/fake-http.service'; +import { CityStore } from '../../data-access/city.store'; +import { + randStudent, + randTeacher, + randomCity, +} 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'; @@ -21,10 +26,15 @@ import { ListItemComponent } from '../list-item/list-item.component'; src="assets/img/student.webp" width="200px" /> + +
@@ -49,6 +59,7 @@ export class CardComponent { constructor( private teacherStore: TeacherStore, private studentStore: StudentStore, + private cityStore: CityStore, ) {} addNewItem() { @@ -56,6 +67,8 @@ export class CardComponent { this.teacherStore.addOne(randTeacher()); } else if (this.type === CardType.STUDENT) { this.studentStore.addOne(randStudent()); + } else if (this.type === CardType.CITY) { + this.cityStore.addOne(randomCity()); } } } diff --git a/apps/angular/projection/src/app/ui/list-item/list-item.component.ts b/apps/angular/projection/src/app/ui/list-item/list-item.component.ts index c0f9cff7f..e6a77dfcb 100644 --- a/apps/angular/projection/src/app/ui/list-item/list-item.component.ts +++ b/apps/angular/projection/src/app/ui/list-item/list-item.component.ts @@ -1,4 +1,5 @@ import { Component, Input } from '@angular/core'; +import { CityStore } from '../../data-access/city.store'; import { StudentStore } from '../../data-access/student.store'; import { TeacherStore } from '../../data-access/teacher.store'; import { CardType } from '../../model/card.model'; @@ -23,6 +24,7 @@ export class ListItemComponent { constructor( private teacherStore: TeacherStore, private studentStore: StudentStore, + private cityStore: CityStore, ) {} delete(id: number) { @@ -30,6 +32,8 @@ export class ListItemComponent { this.teacherStore.deleteOne(id); } else if (this.type === CardType.STUDENT) { this.studentStore.deleteOne(id); + } else if (this.type === CardType.CITY) { + this.cityStore.deleteOne(id); } } } From 11964fa7c94c5e98e6543fc2ab33b5459a95d3a0 Mon Sep 17 00:00:00 2001 From: michal Date: Mon, 25 Mar 2024 08:26:44 +0100 Subject: [PATCH 2/6] fix: correct style css --- .../src/app/component/city-card/city-card.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/angular/projection/src/app/component/city-card/city-card.component.ts b/apps/angular/projection/src/app/component/city-card/city-card.component.ts index 22612eb10..6d9fbe00e 100644 --- a/apps/angular/projection/src/app/component/city-card/city-card.component.ts +++ b/apps/angular/projection/src/app/component/city-card/city-card.component.ts @@ -15,7 +15,7 @@ import { CardComponent } from '../../ui/card/card.component'; `, styles: [ ` - ::ng-deep .bg-light-red { + .bg-light-red { background-color: rgba(250, 0, 0, 0.1); } `, From 981ba9b308889e928ac26607df34aa006e88de25 Mon Sep 17 00:00:00 2001 From: michal Date: Mon, 25 Mar 2024 08:29:12 +0100 Subject: [PATCH 3/6] fix: correct style css v1 --- .../src/app/component/city-card/city-card.component.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/apps/angular/projection/src/app/component/city-card/city-card.component.ts b/apps/angular/projection/src/app/component/city-card/city-card.component.ts index 6d9fbe00e..558e39117 100644 --- a/apps/angular/projection/src/app/component/city-card/city-card.component.ts +++ b/apps/angular/projection/src/app/component/city-card/city-card.component.ts @@ -13,13 +13,6 @@ import { CardComponent } from '../../ui/card/card.component'; [type]="cardType" customClass="bg-light-red"> `, - styles: [ - ` - .bg-light-red { - background-color: rgba(250, 0, 0, 0.1); - } - `, - ], standalone: true, imports: [CardComponent], }) From 2b207fdbccc16f70476d9f8c2005d576985b4392 Mon Sep 17 00:00:00 2001 From: michal Date: Tue, 2 Apr 2024 14:02:06 +0200 Subject: [PATCH 4/6] fix: logic card component --- .../projection/src/app/model/card.model.ts | 8 +++++ .../src/app/services/card.service.ts | 31 +++++++++++++++++++ .../src/app/ui/card/card.component.ts | 25 +++------------ 3 files changed, 43 insertions(+), 21 deletions(-) create mode 100644 apps/angular/projection/src/app/services/card.service.ts diff --git a/apps/angular/projection/src/app/model/card.model.ts b/apps/angular/projection/src/app/model/card.model.ts index 740cd2ae4..0a1533782 100644 --- a/apps/angular/projection/src/app/model/card.model.ts +++ b/apps/angular/projection/src/app/model/card.model.ts @@ -3,3 +3,11 @@ export enum CardType { STUDENT, CITY, } + +export interface CardModel { + name: string; + firstName: string; + lastName: string; + subject: string; + id: number; +} diff --git a/apps/angular/projection/src/app/services/card.service.ts b/apps/angular/projection/src/app/services/card.service.ts new file mode 100644 index 000000000..0f7b6aad2 --- /dev/null +++ b/apps/angular/projection/src/app/services/card.service.ts @@ -0,0 +1,31 @@ +import { Injectable } from '@angular/core'; +import { CityStore } from '../data-access/city.store'; +import { + randomCity, + 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'; + +@Injectable({ + providedIn: 'root', +}) +export class CardService { + constructor( + private teacherStore: TeacherStore, + private studentStore: StudentStore, + private cityStore: CityStore, + ) {} + + addOne(type: CardType) { + if (type === CardType.TEACHER) { + this.teacherStore.addOne(randTeacher()); + } else if (type === CardType.STUDENT) { + this.studentStore.addOne(randStudent()); + } else if (type === CardType.CITY) { + this.cityStore.addOne(randomCity()); + } + } +} diff --git a/apps/angular/projection/src/app/ui/card/card.component.ts b/apps/angular/projection/src/app/ui/card/card.component.ts index 417757cc5..72e912ecd 100644 --- a/apps/angular/projection/src/app/ui/card/card.component.ts +++ b/apps/angular/projection/src/app/ui/card/card.component.ts @@ -1,14 +1,7 @@ import { NgFor, NgIf } from '@angular/common'; import { Component, Input } from '@angular/core'; -import { CityStore } from '../../data-access/city.store'; -import { - randStudent, - randTeacher, - randomCity, -} 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 { CardService } from '../../services/card.service'; import { ListItemComponent } from '../list-item/list-item.component'; @Component({ @@ -50,25 +43,15 @@ import { ListItemComponent } from '../list-item/list-item.component'; imports: [NgIf, NgFor, ListItemComponent], }) export class CardComponent { - @Input() list: any[] | null = null; + @Input() list!: any[]; @Input() type!: CardType; @Input() customClass = ''; CardType = CardType; - constructor( - private teacherStore: TeacherStore, - private studentStore: StudentStore, - private cityStore: CityStore, - ) {} + constructor(private cardService: CardService) {} addNewItem() { - if (this.type === CardType.TEACHER) { - this.teacherStore.addOne(randTeacher()); - } else if (this.type === CardType.STUDENT) { - this.studentStore.addOne(randStudent()); - } else if (this.type === CardType.CITY) { - this.cityStore.addOne(randomCity()); - } + this.cardService.addOne(this.type); } } From 3dd6adf9fb505a799f2129e0bc5c17e32105e9d6 Mon Sep 17 00:00:00 2001 From: michal Date: Thu, 4 Apr 2024 10:34:42 +0200 Subject: [PATCH 5/6] fix: use ng-content, ng-template-outlet an remove CardType --- .../city-card/city-card.component.ts | 2 + .../student-card/student-card.component.ts | 2 + .../teacher-card/teacher-card.component.ts | 2 + .../src/app/ui/card/card.component.ts | 47 ++++++++----------- 4 files changed, 25 insertions(+), 28 deletions(-) diff --git a/apps/angular/projection/src/app/component/city-card/city-card.component.ts b/apps/angular/projection/src/app/component/city-card/city-card.component.ts index 558e39117..714040f85 100644 --- a/apps/angular/projection/src/app/component/city-card/city-card.component.ts +++ b/apps/angular/projection/src/app/component/city-card/city-card.component.ts @@ -11,6 +11,7 @@ import { CardComponent } from '../../ui/card/card.component'; `, standalone: true, @@ -18,6 +19,7 @@ import { CardComponent } from '../../ui/card/card.component'; }) export class CityCardComponent implements OnInit { cities: City[] = []; + image = 'city.png'; cardType = CardType.CITY; constructor( diff --git a/apps/angular/projection/src/app/component/student-card/student-card.component.ts b/apps/angular/projection/src/app/component/student-card/student-card.component.ts index 441cda189..5b97d8ad6 100644 --- a/apps/angular/projection/src/app/component/student-card/student-card.component.ts +++ b/apps/angular/projection/src/app/component/student-card/student-card.component.ts @@ -11,6 +11,7 @@ import { CardComponent } from '../../ui/card/card.component'; `, standalone: true, @@ -26,6 +27,7 @@ import { CardComponent } from '../../ui/card/card.component'; export class StudentCardComponent implements OnInit { students: Student[] = []; cardType = CardType.STUDENT; + image = 'student.webp'; constructor( private http: FakeHttpService, diff --git a/apps/angular/projection/src/app/component/teacher-card/teacher-card.component.ts b/apps/angular/projection/src/app/component/teacher-card/teacher-card.component.ts index 995cb7c2f..bc5699866 100644 --- a/apps/angular/projection/src/app/component/teacher-card/teacher-card.component.ts +++ b/apps/angular/projection/src/app/component/teacher-card/teacher-card.component.ts @@ -11,6 +11,7 @@ import { CardComponent } from '../../ui/card/card.component'; `, styles: [ @@ -26,6 +27,7 @@ import { CardComponent } from '../../ui/card/card.component'; export class TeacherCardComponent implements OnInit { teachers: Teacher[] = []; cardType = CardType.TEACHER; + image = 'teacher.png'; constructor( private http: FakeHttpService, diff --git a/apps/angular/projection/src/app/ui/card/card.component.ts b/apps/angular/projection/src/app/ui/card/card.component.ts index 72e912ecd..a68f64a2f 100644 --- a/apps/angular/projection/src/app/ui/card/card.component.ts +++ b/apps/angular/projection/src/app/ui/card/card.component.ts @@ -1,4 +1,4 @@ -import { NgFor, NgIf } from '@angular/common'; +import { CommonModule } from '@angular/common'; import { Component, Input } from '@angular/core'; import { CardType } from '../../model/card.model'; import { CardService } from '../../services/card.service'; @@ -10,44 +10,35 @@ import { ListItemComponent } from '../list-item/list-item.component';
- - + + - +
+ +
-
- -
+ +
- +
`, standalone: true, - imports: [NgIf, NgFor, ListItemComponent], + imports: [CommonModule, ListItemComponent], }) export class CardComponent { @Input() list!: any[]; @Input() type!: CardType; @Input() customClass = ''; - - CardType = CardType; + @Input() image: string = ''; constructor(private cardService: CardService) {} From 85548b73fedea3a2d27ad0e17bc1fb73c138c16b Mon Sep 17 00:00:00 2001 From: michal Date: Wed, 20 May 2026 18:00:30 +0200 Subject: [PATCH 6/6] feat(Answer:21): anchor for navigation is done --- .../anchor-scrolling/src/app/app.config.ts | 18 +++++++++++-- .../anchor-scrolling/src/app/foo.component.ts | 9 ++++--- .../src/app/home.component.ts | 25 +++++++++++++------ .../src/app/nav-button.component.ts | 8 ++++-- apps/angular/anchor-scrolling/src/styles.scss | 8 ++++++ 5 files changed, 53 insertions(+), 15 deletions(-) diff --git a/apps/angular/anchor-scrolling/src/app/app.config.ts b/apps/angular/anchor-scrolling/src/app/app.config.ts index 66ab7f73f..15f811f8d 100644 --- a/apps/angular/anchor-scrolling/src/app/app.config.ts +++ b/apps/angular/anchor-scrolling/src/app/app.config.ts @@ -1,6 +1,20 @@ import { ApplicationConfig } from '@angular/core'; -import { provideRouter } from '@angular/router'; +import { + provideRouter, + withInMemoryScrolling, + withViewTransitions, +} from '@angular/router'; import { appRoutes } from './app.routes'; + export const appConfig: ApplicationConfig = { - providers: [provideRouter(appRoutes)], + providers: [ + provideRouter( + appRoutes, + withViewTransitions(), + withInMemoryScrolling({ + anchorScrolling: 'enabled', // Enables scrolling to fragments (#id) + scrollPositionRestoration: 'enabled', + }), + ), + ], }; diff --git a/apps/angular/anchor-scrolling/src/app/foo.component.ts b/apps/angular/anchor-scrolling/src/app/foo.component.ts index 87f9b59d9..534bd5037 100644 --- a/apps/angular/anchor-scrolling/src/app/foo.component.ts +++ b/apps/angular/anchor-scrolling/src/app/foo.component.ts @@ -1,15 +1,18 @@ import { Component } from '@angular/core'; +import { RouterLink } from '@angular/router'; import { NavButtonComponent } from './nav-button.component'; @Component({ standalone: true, - imports: [NavButtonComponent], + imports: [NavButtonComponent, RouterLink], selector: 'app-foo', template: ` Welcome to foo page - Home Page + + Home Page +
section 1
-
section 2
+
section 2
`, }) export class FooComponent {} diff --git a/apps/angular/anchor-scrolling/src/app/home.component.ts b/apps/angular/anchor-scrolling/src/app/home.component.ts index 0f24ff6e7..a6fce7745 100644 --- a/apps/angular/anchor-scrolling/src/app/home.component.ts +++ b/apps/angular/anchor-scrolling/src/app/home.component.ts @@ -1,20 +1,29 @@ -import { Component } from '@angular/core'; +import { Component, Output } from '@angular/core'; +import { RouterLink, RouterLinkActive } from '@angular/router'; import { NavButtonComponent } from './nav-button.component'; @Component({ standalone: true, - imports: [NavButtonComponent], + imports: [NavButtonComponent, RouterLink, RouterLinkActive], selector: 'app-home', template: ` - Foo Page -
+ + Foo Page + +
Empty - Scroll Bottom + + Scroll Bottom +
-
+
I want to scroll each - Scroll Top + Scroll Top
`, }) -export class HomeComponent {} +export class HomeComponent { + @Output() links = '.'; + @Output() fragment = ''; + homePath = '.'; +} diff --git a/apps/angular/anchor-scrolling/src/app/nav-button.component.ts b/apps/angular/anchor-scrolling/src/app/nav-button.component.ts index 9e3b6d42f..8ae107b6c 100644 --- a/apps/angular/anchor-scrolling/src/app/nav-button.component.ts +++ b/apps/angular/anchor-scrolling/src/app/nav-button.component.ts @@ -1,17 +1,21 @@ /* eslint-disable @angular-eslint/component-selector */ import { Component, Input } from '@angular/core'; +import { RouterLink } from '@angular/router'; + @Component({ selector: 'nav-button', standalone: true, template: ` - + `, host: { class: 'block w-fit border border-red-500 rounded-md p-4 m-2', }, + imports: [RouterLink], }) export class NavButtonComponent { - @Input() href = ''; + @Input() links: string | string[] = ''; + @Input() fragment = ''; } diff --git a/apps/angular/anchor-scrolling/src/styles.scss b/apps/angular/anchor-scrolling/src/styles.scss index 77e408aa8..6b1f1f0c9 100644 --- a/apps/angular/anchor-scrolling/src/styles.scss +++ b/apps/angular/anchor-scrolling/src/styles.scss @@ -3,3 +3,11 @@ @tailwind utilities; /* You can add global styles to this file, and also import other style files */ +html { + scroll-behavior: smooth; + scroll-snap-type: y mandatory; +} + +body { + overflow-y: scroll; +}