From 53f96ff42143ca6222b8267159c53bd4922bec1d Mon Sep 17 00:00:00 2001 From: Rahib Babayev Date: Tue, 26 Jul 2022 02:20:18 +0400 Subject: [PATCH 1/6] feat: created pagination directiv and directories --- angular.json | 1 + src/app/app.component.html | 8 +- .../components/sidenav/sidenav.component.ts | 14 ++ .../product-card/product-card.component.html | 30 ++-- .../product-card/product-card.component.less | 3 +- .../product-card/product-card.component.ts | 22 ++- .../products-list/products.component.html | 46 +++++- .../products-list/products.component.less | 4 + .../pages/products-list/products.component.ts | 52 +++++-- .../pages/products-list/products.module.ts | 14 +- .../carousel/carousel.directive.spec.ts | 8 + src/app/shared/carousel/carousel.directive.ts | 138 ++++++++++++++++++ src/app/shared/carousel/carousel.module.ts | 10 ++ src/app/shared/for/for.directive.spec.ts | 8 + src/app/shared/for/for.directive.ts | 25 ++++ src/app/shared/for/for.module.ts | 10 ++ .../pagination-directive.interface.ts | 7 + .../pagination/pagination.directive.spec.ts | 8 + .../shared/pagination/pagination.directive.ts | 64 ++++++++ .../shared/pagination/pagination.module.ts | 10 ++ 20 files changed, 445 insertions(+), 37 deletions(-) create mode 100644 src/app/shared/carousel/carousel.directive.spec.ts create mode 100644 src/app/shared/carousel/carousel.directive.ts create mode 100644 src/app/shared/carousel/carousel.module.ts create mode 100644 src/app/shared/for/for.directive.spec.ts create mode 100644 src/app/shared/for/for.directive.ts create mode 100644 src/app/shared/for/for.module.ts create mode 100644 src/app/shared/pagination/interfaces/pagination-directive.interface.ts create mode 100644 src/app/shared/pagination/pagination.directive.spec.ts create mode 100644 src/app/shared/pagination/pagination.directive.ts create mode 100644 src/app/shared/pagination/pagination.module.ts diff --git a/angular.json b/angular.json index b255a7e..d926e78 100644 --- a/angular.json +++ b/angular.json @@ -112,6 +112,7 @@ }, "defaultProject": "Angular-learnjs-130622", "cli": { + "analytics": false, "defaultCollection": "@angular-eslint/schematics" } } diff --git a/src/app/app.component.html b/src/app/app.component.html index 3b61242..8ab0559 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -2,7 +2,11 @@ - + + + + + Item 1 @@ -11,4 +15,4 @@ - \ No newline at end of file + diff --git a/src/app/components/sidenav/sidenav.component.ts b/src/app/components/sidenav/sidenav.component.ts index eed51ce..d9610ac 100644 --- a/src/app/components/sidenav/sidenav.component.ts +++ b/src/app/components/sidenav/sidenav.component.ts @@ -45,5 +45,19 @@ export class SidenavComponent implements OnInit { private insertList(template: TemplateRef) { this.drawerViewPortElement.clear(); this.drawerViewPortElement.createEmbeddedView(template); + + // setTimeout(() => { + // this.drawerViewPortElement.clear(); + // this.drawerViewPortElement.createEmbeddedView(template, + // { + // name: 'Egor', + // $implicit: 'Angular LearnJs', + // user: { + // age: '35', + // } + // }); + // + // this.changeDetectorRef.markForCheck(); + // }, 3000) } } diff --git a/src/app/pages/products-list/product-card/product-card.component.html b/src/app/pages/products-list/product-card/product-card.component.html index 8dec404..c36c7bb 100644 --- a/src/app/pages/products-list/product-card/product-card.component.html +++ b/src/app/pages/products-list/product-card/product-card.component.html @@ -3,20 +3,22 @@ {{product?.name}} {{product?.price}} Р -
- - Product photo - -
+ +
+ + Product photo + +
+ - \ No newline at end of file + diff --git a/src/app/pages/products-list/product-card/product-card.component.less b/src/app/pages/products-list/product-card/product-card.component.less index ce7648f..528d053 100644 --- a/src/app/pages/products-list/product-card/product-card.component.less +++ b/src/app/pages/products-list/product-card/product-card.component.less @@ -3,7 +3,8 @@ } .card { - width: 100%; + width: 500px; + margin-bottom: 10px; box-sizing: border-box; display: flex; flex-direction: column; diff --git a/src/app/pages/products-list/product-card/product-card.component.ts b/src/app/pages/products-list/product-card/product-card.component.ts index afab068..aabaacf 100644 --- a/src/app/pages/products-list/product-card/product-card.component.ts +++ b/src/app/pages/products-list/product-card/product-card.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core'; +import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { IProduct } from '../../../shared/products/product.interface'; @Component({ @@ -7,8 +7,8 @@ import { IProduct } from '../../../shared/products/product.interface'; styleUrls: ['./product-card.component.less'], changeDetection: ChangeDetectionStrategy.OnPush, }) -export class ProductCardComponent { - @Input() product!: IProduct; +export class ProductCardComponent implements OnInit { + @Input() product: IProduct | undefined; @Output() buyProduct = new EventEmitter(); @@ -17,4 +17,20 @@ export class ProductCardComponent { this.buyProduct.emit(); } + + // prev!: () => void; + // next!: () => void; + // + // onRegisterPrev(fn: () => void) { + // this.prev = fn; + // } + // + + get imgSrc(): string { + return this.product?.images[0].url || ''; + } + + ngOnInit() { + console.log('ProductCardComponent created'); + } } diff --git a/src/app/pages/products-list/products.component.html b/src/app/pages/products-list/products.component.html index 6e57a9b..b4a8954 100644 --- a/src/app/pages/products-list/products.component.html +++ b/src/app/pages/products-list/products.component.html @@ -1,5 +1,43 @@ - - - - +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + diff --git a/src/app/pages/products-list/products.component.less b/src/app/pages/products-list/products.component.less index 885c68c..397214f 100644 --- a/src/app/pages/products-list/products.component.less +++ b/src/app/pages/products-list/products.component.less @@ -15,3 +15,7 @@ // color: red; // background-color: red; // } + +.spinner { + margin: 0 auto; +} diff --git a/src/app/pages/products-list/products.component.ts b/src/app/pages/products-list/products.component.ts index 703fd21..4bb23fb 100644 --- a/src/app/pages/products-list/products.component.ts +++ b/src/app/pages/products-list/products.component.ts @@ -1,5 +1,6 @@ -import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@angular/core'; import { productsMock } from '../../shared/products/products.mock'; +import { IProduct } from '../../shared/products/product.interface'; @Component({ selector: 'app-products', @@ -7,19 +8,46 @@ import { productsMock } from '../../shared/products/products.mock'; styleUrls: ['./products.component.less'], changeDetection: ChangeDetectionStrategy.OnPush, }) -export class ProductsComponent { - products = productsMock; +export class ProductsComponent implements OnInit { + products: IProduct[] | undefined = undefined; // isHovered = true; - // constructor( - // private changeDetectorRef: ChangeDetectorRef, - // ) {} + constructor(private changeDetectorRef: ChangeDetectorRef) {} - // ngOnInit() { - // setTimeout(() => { - // this.isHovered = false; - // this.changeDetectorRef.markForCheck(); - // }, 3000) - // } + ngOnInit() { + // setTimeout(() => { + // this.products = productsMock.slice(0, 4); + // this.changeDetectorRef.markForCheck(); + // }, 2000) + // + // setTimeout(() => { + // console.log(' ') + // }, 3000) + + setTimeout(() => { + this.products = productsMock.map((item) => ({ ...item })); + this.changeDetectorRef.markForCheck(); + }, 2000); + // + // setTimeout(() => { + // console.log(' ') + // }, 6000) + + setTimeout(() => { + // this.products = productsMock.map(item => ({...item, name: item.name + '1245'})); + // this.products?.forEach((_, index: number) => { + // if (this.products) { + // this.products[index].name = '1345'; + // } + // }) + this.changeDetectorRef.markForCheck(); + }, 3000); + } + + trackBy(_: number, item: IProduct) { + return item._id; + // return item.name; + // return item; + } } diff --git a/src/app/pages/products-list/products.module.ts b/src/app/pages/products-list/products.module.ts index 7cc3a97..3394aec 100644 --- a/src/app/pages/products-list/products.module.ts +++ b/src/app/pages/products-list/products.module.ts @@ -6,10 +6,22 @@ import { MatCardModule } from '@angular/material/card'; import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; import { NgClassModule } from '../../shared/ng-class/ng-class.module'; +import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; +import { ForModule } from '../../shared/for/for.module'; +import { CarouselModule } from '../../shared/carousel/carousel.module'; @NgModule({ declarations: [ProductsComponent, ProductCardComponent], - imports: [CommonModule, MatCardModule, MatButtonModule, MatIconModule, NgClassModule], + imports: [ + CommonModule, + MatCardModule, + MatButtonModule, + MatIconModule, + NgClassModule, + MatProgressSpinnerModule, + ForModule, + CarouselModule, + ], exports: [ProductsComponent], }) export class ProductsModule {} diff --git a/src/app/shared/carousel/carousel.directive.spec.ts b/src/app/shared/carousel/carousel.directive.spec.ts new file mode 100644 index 0000000..9675cbe --- /dev/null +++ b/src/app/shared/carousel/carousel.directive.spec.ts @@ -0,0 +1,8 @@ +import { CarouselDirective } from './carousel.directive'; + +describe('CarouselDirective', () => { + it('should create an instance', () => { + const directive = new CarouselDirective(); + expect(directive).toBeTruthy(); + }); +}); diff --git a/src/app/shared/carousel/carousel.directive.ts b/src/app/shared/carousel/carousel.directive.ts new file mode 100644 index 0000000..d0c21c9 --- /dev/null +++ b/src/app/shared/carousel/carousel.directive.ts @@ -0,0 +1,138 @@ +import { Directive, EventEmitter, Input, OnInit, Output, TemplateRef, ViewContainerRef } from '@angular/core'; +import { BehaviorSubject, filter, map, withLatestFrom } from 'rxjs'; + +interface ICarouselDirective { + $implicit: T; + index: number; + prev: () => void; + next: () => void; +} + +@Directive({ + selector: '[appCarousel]', +}) +export class CarouselDirective implements OnInit { + @Input() set appCarouselOf(items: T[] | undefined) { + console.log(items, 'item in from component'); + // if (!(items && items.length)) { + // this.viewContainerRef.clear(); + // } + + if (!items?.length) { + this.viewContainerRef.clear(); + + return; + } + + // this.items = items; + + this.items$.next(items); + this.currentIndex$.next(0); + + // this.currentIndex = 0; + // this.insertTemplateWithCurrentIndex(); + } + + // + // @Output() emitNext = new EventEmitter<() => void>(); + // @Output() emitPrev = new EventEmitter<() => void>(); + + // private items: T[] | undefined = undefined; + private readonly items$ = new BehaviorSubject(undefined); + // private currentIndex: number = 0; + + private readonly currentIndex$ = new BehaviorSubject(0); + + constructor(private templateRef: TemplateRef>, private viewContainerRef: ViewContainerRef) {} + + ngOnInit() { + this.listenCurrentIndexChange(); + // this.emitPrev.emit(this.prev.bind(this)); + // this.emitNext.emit(() => { + // this.next(); + // }); + } + + private listenCurrentIndexChange() { + this.currentIndex$ + .pipe( + withLatestFrom(this.items$.pipe(filter(Boolean))), + map(([index, items]) => this.getCurrentContext(index, items)) + ) + .subscribe((context) => { + // this.insertTemplateWithCurrentIndex(); + this.viewContainerRef.clear(); + this.viewContainerRef.createEmbeddedView(this.templateRef, context); + }); + } + + // метод вставки темплейта с выбранным индексом + // private insertTemplateWithCurrentIndex() { + // this.viewContainerRef.clear(); // зачищаем viewContainer. + // this.viewContainerRef.createEmbeddedView(this.templateRef, this.getCurrentContext(this.currentIndex, this.items as T[])); + // } + + private getCurrentContext(index: number, items: T[]): ICarouselDirective { + return { + index, + $implicit: items[index], + prev: this.prev.bind(this), + next: () => { + this.next(); + }, + }; + } + + private next() { + // const nextIndex = this.currentIndex + 1; + // const itemsLength = this.items?.length; + + const nextIndex = this.currentIndex$.value + 1; + const itemsLength = this.items$.value?.length; + + console.log('next method'); + + if (!itemsLength) { + return; + } + + // short version + // this.currentIndex = nextIndex < itemsLength ? nextIndex : 0; + this.currentIndex$.next(nextIndex < itemsLength ? nextIndex : 0); + + // if (nextIndex < itemsLength) { + // this.currentIndex = nextIndex; + // this.insertTemplateWithCurrentIndex(); + // return; + // } + // this.currentIndex = 0; + // this.insertTemplateWithCurrentIndex(); + } + + private prev() { + // const prevIndex = this.currentIndex - 1; + // const itemsLength = this.items?.length; + + const prevIndex = this.currentIndex$.value - 1; + const itemsLength = this.items$.value?.length; + + console.log('prev method'); + + if (!itemsLength) { + return; + } + + // short version + // this.currentIndex = prevIndex >= 0 ? prevIndex : itemsLength - 1; + + this.currentIndex$.next(prevIndex >= 0 ? prevIndex : itemsLength - 1); + // if (prevIndex >= 0) { + // this.currentIndex = prevIndex; + // this.insertTemplateWithCurrentIndex(); + // return; + // } + + // this.currentIndex = itemsLength - 1; + // this.insertTemplateWithCurrentIndex(); + } +} diff --git a/src/app/shared/carousel/carousel.module.ts b/src/app/shared/carousel/carousel.module.ts new file mode 100644 index 0000000..2a3ac43 --- /dev/null +++ b/src/app/shared/carousel/carousel.module.ts @@ -0,0 +1,10 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { CarouselDirective } from './carousel.directive'; + +@NgModule({ + declarations: [CarouselDirective], + imports: [CommonModule], + exports: [CarouselDirective], +}) +export class CarouselModule {} diff --git a/src/app/shared/for/for.directive.spec.ts b/src/app/shared/for/for.directive.spec.ts new file mode 100644 index 0000000..53d9e76 --- /dev/null +++ b/src/app/shared/for/for.directive.spec.ts @@ -0,0 +1,8 @@ +import { ForDirective } from './for.directive'; + +describe('ForDirective', () => { + it('should create an instance', () => { + const directive = new ForDirective(); + expect(directive).toBeTruthy(); + }); +}); diff --git a/src/app/shared/for/for.directive.ts b/src/app/shared/for/for.directive.ts new file mode 100644 index 0000000..5dcee79 --- /dev/null +++ b/src/app/shared/for/for.directive.ts @@ -0,0 +1,25 @@ +import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core'; + +interface IContextAppFor { + $implicit: T; +} + +// IContextAppFor => $implicit: Product; +// IContextAppFor => $implicit: string; + +@Directive({ + selector: '[appFor]', +}) +export class ForDirective { + @Input() set appForOf(array: T[]) { + this.viewContainerRef.clear(); + if (array) { + array.forEach((item) => { + const context: IContextAppFor = { $implicit: item }; + this.viewContainerRef.createEmbeddedView(this.templateRef, context); + }); + } + } + + constructor(private templateRef: TemplateRef>, private viewContainerRef: ViewContainerRef) {} +} diff --git a/src/app/shared/for/for.module.ts b/src/app/shared/for/for.module.ts new file mode 100644 index 0000000..f03967c --- /dev/null +++ b/src/app/shared/for/for.module.ts @@ -0,0 +1,10 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ForDirective } from './for.directive'; + +@NgModule({ + declarations: [ForDirective], + imports: [CommonModule], + exports: [ForDirective], +}) +export class ForModule {} diff --git a/src/app/shared/pagination/interfaces/pagination-directive.interface.ts b/src/app/shared/pagination/interfaces/pagination-directive.interface.ts new file mode 100644 index 0000000..c41cb91 --- /dev/null +++ b/src/app/shared/pagination/interfaces/pagination-directive.interface.ts @@ -0,0 +1,7 @@ +export interface IPaginationDirective { + $implicit: T; + index: number; + prev: () => void; + next: () => void; + activeIndex: () => void; +} diff --git a/src/app/shared/pagination/pagination.directive.spec.ts b/src/app/shared/pagination/pagination.directive.spec.ts new file mode 100644 index 0000000..8ce8792 --- /dev/null +++ b/src/app/shared/pagination/pagination.directive.spec.ts @@ -0,0 +1,8 @@ +import { PaginationDirective } from './pagination.directive'; + +describe('PaginationDirective', () => { + it('should create an instance', () => { + const directive = new PaginationDirective(); + expect(directive).toBeTruthy(); + }); +}); diff --git a/src/app/shared/pagination/pagination.directive.ts b/src/app/shared/pagination/pagination.directive.ts new file mode 100644 index 0000000..23a8ee8 --- /dev/null +++ b/src/app/shared/pagination/pagination.directive.ts @@ -0,0 +1,64 @@ +import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core'; +import { IPaginationDirective } from './interfaces/pagination-directive.interface'; + +@Directive({ + selector: '[appPagination]', +}) +export class PaginationDirective { + @Input() set appPaginationOf(items: T[] | undefined) { + // если у нас длина элемента боль нуля, то есть если нам пришел маассив с новыми элементами то мы должы очистить предыдуший + if (!(items && items.length)) { + this.viewContainerRef.clear(); + } + + this.items = items; + this.currentIndex = 0; + } + + private items: T[] | undefined = undefined; + private currentIndex: number = 0; + + constructor( + private templateRef: TemplateRef>, + private viewContainerRef: ViewContainerRef + ) {} + + // ngOnInit() {} + + private insertTemplateWithCurrentIndex() { + this.viewContainerRef.clear(); + this.viewContainerRef.createEmbeddedView( + this.templateRef, + this.getCurrentContext(this.currentIndex, this.items as T[]) + ); + } + + private getCurrentContext(index: number, items: T[]): IPaginationDirective { + return { + index, + $implicit: items[index], + prev: () => { + this.prev(); + }, + next: () => { + this.next(); + }, + activeIndex: () => { + this.currentActivePage(); + }, + }; + } + + currentActivePage() {} + + prev() {} + + next() { + const currentNextIndex = this.currentIndex + 1; + const itemsLength = this.items?.length; + + // if () { + // + // } + } +} diff --git a/src/app/shared/pagination/pagination.module.ts b/src/app/shared/pagination/pagination.module.ts new file mode 100644 index 0000000..0a61525 --- /dev/null +++ b/src/app/shared/pagination/pagination.module.ts @@ -0,0 +1,10 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { PaginationDirective } from './pagination.directive'; + +@NgModule({ + declarations: [PaginationDirective], + imports: [CommonModule], + exports: [PaginationDirective], +}) +export class PaginationModule {} From 94c788a4910cad3bd6afd28eb56bad2f449c3f42 Mon Sep 17 00:00:00 2001 From: Rahib Babayev Date: Sat, 30 Jul 2022 21:43:52 +0400 Subject: [PATCH 2/6] feat: created pagination directive logic --- .../products-list/products.component.html | 35 +++++------ .../pages/products-list/products.module.ts | 2 + src/app/shared/carousel/carousel.directive.ts | 2 +- .../pagination-directive.interface.ts | 4 +- .../shared/pagination/pagination.directive.ts | 60 +++++++++++++++---- 5 files changed, 72 insertions(+), 31 deletions(-) diff --git a/src/app/pages/products-list/products.component.html b/src/app/pages/products-list/products.component.html index b4a8954..48254b4 100644 --- a/src/app/pages/products-list/products.component.html +++ b/src/app/pages/products-list/products.component.html @@ -1,6 +1,6 @@
- + @@ -8,8 +8,9 @@ - + + {{product}} @@ -21,20 +22,20 @@ - - - - - - - - - - - - - - + +
diff --git a/src/app/pages/products-list/products.module.ts b/src/app/pages/products-list/products.module.ts index 3394aec..7e9036e 100644 --- a/src/app/pages/products-list/products.module.ts +++ b/src/app/pages/products-list/products.module.ts @@ -9,6 +9,7 @@ import { NgClassModule } from '../../shared/ng-class/ng-class.module'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { ForModule } from '../../shared/for/for.module'; import { CarouselModule } from '../../shared/carousel/carousel.module'; +import { PaginationModule } from '../../shared/pagination/pagination.module'; @NgModule({ declarations: [ProductsComponent, ProductCardComponent], @@ -21,6 +22,7 @@ import { CarouselModule } from '../../shared/carousel/carousel.module'; MatProgressSpinnerModule, ForModule, CarouselModule, + PaginationModule, ], exports: [ProductsComponent], }) diff --git a/src/app/shared/carousel/carousel.directive.ts b/src/app/shared/carousel/carousel.directive.ts index d0c21c9..ac1785d 100644 --- a/src/app/shared/carousel/carousel.directive.ts +++ b/src/app/shared/carousel/carousel.directive.ts @@ -75,7 +75,7 @@ export class CarouselDirective implements OnInit { private getCurrentContext(index: number, items: T[]): ICarouselDirective { return { index, - $implicit: items[index], + $implicit: items[index], // items c необходимым индексом. prev: this.prev.bind(this), next: () => { this.next(); diff --git a/src/app/shared/pagination/interfaces/pagination-directive.interface.ts b/src/app/shared/pagination/interfaces/pagination-directive.interface.ts index c41cb91..d970610 100644 --- a/src/app/shared/pagination/interfaces/pagination-directive.interface.ts +++ b/src/app/shared/pagination/interfaces/pagination-directive.interface.ts @@ -1,7 +1,7 @@ export interface IPaginationDirective { - $implicit: T; + $implicit: T | T[]; index: number; prev: () => void; next: () => void; - activeIndex: () => void; + activeIndex: (index: number) => void; } diff --git a/src/app/shared/pagination/pagination.directive.ts b/src/app/shared/pagination/pagination.directive.ts index 23a8ee8..a70811a 100644 --- a/src/app/shared/pagination/pagination.directive.ts +++ b/src/app/shared/pagination/pagination.directive.ts @@ -1,10 +1,10 @@ -import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core'; +import { Directive, Input, OnInit, Output, TemplateRef, ViewContainerRef } from '@angular/core'; import { IPaginationDirective } from './interfaces/pagination-directive.interface'; @Directive({ selector: '[appPagination]', }) -export class PaginationDirective { +export class PaginationDirective implements OnInit { @Input() set appPaginationOf(items: T[] | undefined) { // если у нас длина элемента боль нуля, то есть если нам пришел маассив с новыми элементами то мы должы очистить предыдуший if (!(items && items.length)) { @@ -15,6 +15,13 @@ export class PaginationDirective { this.currentIndex = 0; } + @Input() set activePageIndex(pageIndex: number) { + this.pageIndex = pageIndex; + } + + @Output() + pageIndex: number = 4; + private items: T[] | undefined = undefined; private currentIndex: number = 0; @@ -23,7 +30,10 @@ export class PaginationDirective { private viewContainerRef: ViewContainerRef ) {} - // ngOnInit() {} + ngOnInit() { + console.log(this.items, 'items from products'); + console.log(this.items?.[0], 'items from products'); + } private insertTemplateWithCurrentIndex() { this.viewContainerRef.clear(); @@ -43,22 +53,50 @@ export class PaginationDirective { next: () => { this.next(); }, - activeIndex: () => { - this.currentActivePage(); + activeIndex: (index: number) => { + this.currentActivePage(index); }, }; } - currentActivePage() {} + currentActivePage(index: number) {} - prev() {} + prev() { + const prevIndex = this.currentIndex - 1; + const itemsLength = this.items?.length; + + if (!itemsLength) { + return; + } + + if (prevIndex >= 0) { + this.currentIndex = prevIndex; + this.insertTemplateWithCurrentIndex(); + return; + } + + // если он у нас prevIndex меньше нуля, то есть если это бесконечная itemsLength - 1, то есть последний индекс массива. + this.currentIndex = itemsLength - 1; + + this.insertTemplateWithCurrentIndex(); + } next() { - const currentNextIndex = this.currentIndex + 1; + const nextIndex = this.currentIndex + 1; const itemsLength = this.items?.length; - // if () { - // - // } + if (!itemsLength) { + return; + } + + if (nextIndex < itemsLength) { + this.currentIndex = nextIndex; + this.insertTemplateWithCurrentIndex(); + return; + } + + // когда следущуюий индек больше или равен длине массима тогда зануляем currentIndex. + this.currentIndex = 0; + this.insertTemplateWithCurrentIndex(); } } From 8bf31ed94747fb74a430f4c7a5e39fb8b732e5c7 Mon Sep 17 00:00:00 2001 From: Rahib Babayev Date: Sun, 31 Jul 2022 05:13:13 +0400 Subject: [PATCH 3/6] feat: pagination directive logic --- .../product-card/product-card.component.ts | 8 ++++---- .../products-list/products.component.html | 18 ++++++++++++++++-- .../pagination-directive.interface.ts | 3 ++- .../shared/pagination/pagination.directive.ts | 3 ++- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/app/pages/products-list/product-card/product-card.component.ts b/src/app/pages/products-list/product-card/product-card.component.ts index aabaacf..3c84dc5 100644 --- a/src/app/pages/products-list/product-card/product-card.component.ts +++ b/src/app/pages/products-list/product-card/product-card.component.ts @@ -26,11 +26,11 @@ export class ProductCardComponent implements OnInit { // } // - get imgSrc(): string { - return this.product?.images[0].url || ''; - } + // get imgSrc(): string { + // return this.product?.images[0].url || ''; + // } ngOnInit() { - console.log('ProductCardComponent created'); + console.log(this.product, 'ProductCardComponent created'); } } diff --git a/src/app/pages/products-list/products.component.html b/src/app/pages/products-list/products.component.html index 48254b4..64ba686 100644 --- a/src/app/pages/products-list/products.component.html +++ b/src/app/pages/products-list/products.component.html @@ -1,6 +1,13 @@
- + @@ -28,7 +35,14 @@ chevron_left - {{index}} + + diff --git a/src/app/pages/products-list/products.component.less b/src/app/pages/products-list/products.component.less index 397214f..e772d39 100644 --- a/src/app/pages/products-list/products.component.less +++ b/src/app/pages/products-list/products.component.less @@ -19,3 +19,13 @@ .spinner { margin: 0 auto; } + +.pagination { + display: flex; + align-items: center; + &__button { + &--active { + color: red; + } + } +} diff --git a/src/app/pages/products-list/products.component.ts b/src/app/pages/products-list/products.component.ts index 4bb23fb..e04e3cd 100644 --- a/src/app/pages/products-list/products.component.ts +++ b/src/app/pages/products-list/products.component.ts @@ -1,6 +1,7 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@angular/core'; import { productsMock } from '../../shared/products/products.mock'; import { IProduct } from '../../shared/products/product.interface'; +import { Subject } from 'rxjs'; @Component({ selector: 'app-products', @@ -11,8 +12,7 @@ import { IProduct } from '../../shared/products/product.interface'; export class ProductsComponent implements OnInit { products: IProduct[] | undefined = undefined; - // isHovered = true; - + items = [2, 34, 5, 6, 7, 3, 3, 5, 4]; constructor(private changeDetectorRef: ChangeDetectorRef) {} ngOnInit() { @@ -25,6 +25,7 @@ export class ProductsComponent implements OnInit { // console.log(' ') // }, 3000) + console.log(this.items.slice(2, 4), 'slice'); setTimeout(() => { this.products = productsMock.map((item) => ({ ...item })); this.changeDetectorRef.markForCheck(); diff --git a/src/app/shared/pagination/pagination.directive.ts b/src/app/shared/pagination/pagination.directive.ts index 714401a..67fdf93 100644 --- a/src/app/shared/pagination/pagination.directive.ts +++ b/src/app/shared/pagination/pagination.directive.ts @@ -1,4 +1,4 @@ -import { Directive, Input, OnInit, Output, TemplateRef, ViewContainerRef } from '@angular/core'; +import { Directive, EventEmitter, Input, OnInit, Output, TemplateRef, ViewContainerRef } from '@angular/core'; import { IPaginationDirective } from './interfaces/pagination-directive.interface'; @Directive({ @@ -13,17 +13,16 @@ export class PaginationDirective implements OnInit { this.items = items; this.currentIndex = 0; - } - @Input() set activePageIndex(pageIndex: number) { - this.pageIndex = pageIndex; + this.insertTemplateWithCurrentIndex(); } - @Output() - pageIndex: number = 4; + @Input('appPaginationElementSize') elementSize = 1; + @Output() emitSelectedIndex = new EventEmitter<() => void>(); private items: T[] | undefined = undefined; private currentIndex: number = 0; + private allItems: T[] | undefined = undefined; constructor( private templateRef: TemplateRef>, @@ -32,7 +31,7 @@ export class PaginationDirective implements OnInit { ngOnInit() { console.log(this.items, 'items from products'); - console.log(this.items?.[0], 'items from products'); + this.allItems = this.items; } private insertTemplateWithCurrentIndex() { @@ -55,12 +54,15 @@ export class PaginationDirective implements OnInit { }, allIndexes: items.map((_, index) => index), selectIndex: (index: number) => { - this.currentActivePage(index); + this.activeSelectedIndex(index); }, }; } - currentActivePage(index: number) {} + private activeSelectedIndex(index: number) { + // this.emitSelectedIndex(index) + console.log(index, 'index from template'); + } prev() { const prevIndex = this.currentIndex - 1; From b1d1fe80d1722d2bd3c8d3999b6f3676e93ae7e5 Mon Sep 17 00:00:00 2001 From: Rahib Babayev Date: Mon, 22 Aug 2022 20:10:35 +0400 Subject: [PATCH 5/6] feat: pagination changes --- src/app/shared/pagination/pagination.directive.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/shared/pagination/pagination.directive.ts b/src/app/shared/pagination/pagination.directive.ts index 67fdf93..d8aef67 100644 --- a/src/app/shared/pagination/pagination.directive.ts +++ b/src/app/shared/pagination/pagination.directive.ts @@ -30,7 +30,6 @@ export class PaginationDirective implements OnInit { ) {} ngOnInit() { - console.log(this.items, 'items from products'); this.allItems = this.items; } From 4bded750a73995a027e36c2e94a56b69f0bfe5f3 Mon Sep 17 00:00:00 2001 From: Rahib Babayev Date: Sat, 10 Sep 2022 16:53:34 +0400 Subject: [PATCH 6/6] fix: lesson-6: pagination directive bug fixing --- .../shared/pagination/pagination.directive.ts | 63 ++++++++++++++----- 1 file changed, 46 insertions(+), 17 deletions(-) diff --git a/src/app/shared/pagination/pagination.directive.ts b/src/app/shared/pagination/pagination.directive.ts index d8aef67..655ed6a 100644 --- a/src/app/shared/pagination/pagination.directive.ts +++ b/src/app/shared/pagination/pagination.directive.ts @@ -1,28 +1,27 @@ -import { Directive, EventEmitter, Input, OnInit, Output, TemplateRef, ViewContainerRef } from '@angular/core'; +import { + Directive, + EventEmitter, + Input, + OnChanges, + OnInit, + Output, + SimpleChanges, + TemplateRef, + ViewContainerRef, +} from '@angular/core'; import { IPaginationDirective } from './interfaces/pagination-directive.interface'; @Directive({ selector: '[appPagination]', }) -export class PaginationDirective implements OnInit { - @Input() set appPaginationOf(items: T[] | undefined) { - // если у нас длина элемента боль нуля, то есть если нам пришел маассив с новыми элементами то мы должы очистить предыдуший - if (!(items && items.length)) { - this.viewContainerRef.clear(); - } - - this.items = items; - this.currentIndex = 0; - - this.insertTemplateWithCurrentIndex(); - } - +export class PaginationDirective implements OnInit, OnChanges { + @Input() appPaginationOf: T[] | undefined; @Input('appPaginationElementSize') elementSize = 1; @Output() emitSelectedIndex = new EventEmitter<() => void>(); - private items: T[] | undefined = undefined; + private items: T[] | Array | undefined = undefined; private currentIndex: number = 0; - private allItems: T[] | undefined = undefined; + // private allItems: T[] | undefined = undefined; constructor( private templateRef: TemplateRef>, @@ -30,7 +29,37 @@ export class PaginationDirective implements OnInit { ) {} ngOnInit() { - this.allItems = this.items; + console.log(this.appPaginationOf, 'appPaginationOf'); + } + + ngOnChanges({ appPaginationOf, appPaginationElementSize }: SimpleChanges) { + if (appPaginationOf || appPaginationElementSize) { + if (!(this.appPaginationOf && this.appPaginationOf.length)) { + this.viewContainerRef.clear(); + } + } + + this.items = this.elementSize > 1 ? this.getGroupedItemsListByElementsSize() : this.appPaginationOf; + this.currentIndex = 0; + + this.insertTemplateWithCurrentIndex(); + } + + private getGroupedItemsListByElementsSize() { + return this.appPaginationOf?.reduce( + (acc: Array, item: T): Array => { + const lastGroupIndex = acc.length - 1; + const lastGroupLength = acc[lastGroupIndex].length; + + if (lastGroupLength === this.elementSize) { + return [...acc, [item]]; + } + + acc[lastGroupIndex].push(item); + return [...acc]; + }, + [[]] + ); } private insertTemplateWithCurrentIndex() {