From c8ee9abac1c86d76b1563089e3ecbb52a960649b Mon Sep 17 00:00:00 2001 From: waterplea Date: Fri, 17 Jan 2025 11:54:43 +0400 Subject: [PATCH 1/3] fix(experimental): `Accordion` fix error with dynamic items --- .../accordion/examples/1/index.html | 14 ++--- .../components/accordion/examples/1/index.ts | 14 ++++- .../accordion/accordion.component.ts | 51 ++++++++++++------- .../accordion/accordion.directive.ts | 5 +- .../components/expand/expand.component.ts | 13 +++++ 5 files changed, 65 insertions(+), 32 deletions(-) diff --git a/projects/demo/src/modules/components/accordion/examples/1/index.html b/projects/demo/src/modules/components/accordion/examples/1/index.html index 7635488ab1b7..c219f078ba52 100644 --- a/projects/demo/src/modules/components/accordion/examples/1/index.html +++ b/projects/demo/src/modules/components/accordion/examples/1/index.html @@ -1,12 +1,6 @@ - - - Development kit consisting of the low level tools and abstractions used to develop Taiga UI Angular entities - - - - Basic elements needed to develop components, directives and more using Taiga UI design system - - - The main set of components used to build Taiga UI based Angular applications + + + {{ item.value }} + diff --git a/projects/demo/src/modules/components/accordion/examples/1/index.ts b/projects/demo/src/modules/components/accordion/examples/1/index.ts index 040c8b435ad5..e1b45ec57686 100644 --- a/projects/demo/src/modules/components/accordion/examples/1/index.ts +++ b/projects/demo/src/modules/components/accordion/examples/1/index.ts @@ -1,3 +1,4 @@ +import {KeyValuePipe, NgForOf} from '@angular/common'; import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; @@ -5,9 +6,18 @@ import {TuiAccordion} from '@taiga-ui/experimental'; @Component({ standalone: true, - imports: [TuiAccordion], + imports: [TuiAccordion, NgForOf, KeyValuePipe], templateUrl: './index.html', encapsulation, changeDetection, }) -export default class Example {} +export default class Example { + protected readonly data = { + 'Taiga UI cdk': + 'Development kit consisting of the low level tools and abstractions used to develop Taiga UI Angular entities', + 'Taiga UI core': + 'Basic elements needed to develop components, directives and more using Taiga UI design system', + 'Taiga UI kit': + 'The main set of components used to build Taiga UI based Angular applications', + }; +} diff --git a/projects/experimental/components/accordion/accordion.component.ts b/projects/experimental/components/accordion/accordion.component.ts index cb865477c5e4..17b010d13c07 100644 --- a/projects/experimental/components/accordion/accordion.component.ts +++ b/projects/experimental/components/accordion/accordion.component.ts @@ -1,16 +1,21 @@ -import type {QueryList} from '@angular/core'; import { + type AfterViewInit, ChangeDetectionStrategy, Component, ContentChildren, + DestroyRef, + inject, Input, + type QueryList, signal, ViewEncapsulation, } from '@angular/core'; +import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; import {EMPTY_QUERY} from '@taiga-ui/cdk/constants'; import {TuiGroup, tuiGroupOptionsProvider} from '@taiga-ui/core/directives/group'; import type {TuiSizeL, TuiSizeS} from '@taiga-ui/core/types'; import {TuiExpand} from '@taiga-ui/experimental/components/expand'; +import {ReplaySubject} from 'rxjs'; import {TuiAccordionDirective} from './accordion.directive'; @@ -32,11 +37,14 @@ import {TuiAccordionDirective} from './accordion.directive'; '[attr.data-size]': 'size()', }, }) -export class TuiAccordionComponent { - @ContentChildren(TuiExpand, {static: true} as any) +export class TuiAccordionComponent implements AfterViewInit { + private readonly destroyRef = inject(DestroyRef); + private readonly toggle$ = new ReplaySubject(); + + @ContentChildren(TuiExpand) public readonly expands: QueryList = EMPTY_QUERY; - @ContentChildren(TuiAccordionDirective, {static: true} as any) + @ContentChildren(TuiAccordionDirective) public readonly directives: QueryList = EMPTY_QUERY; @Input() @@ -49,22 +57,29 @@ export class TuiAccordionComponent { this.size.set(size); } - public toggle(directive: TuiAccordionDirective, value: boolean): void { - if (this.closeOthers && value) { - this.expands.forEach((expand) => { - expand.expanded = false; - }); + public ngAfterViewInit(): void { + this.toggle$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((d) => { + if (this.closeOthers && d.open()) { + this.expands.forEach((expand) => { + expand.expanded = false; + }); + + this.directives.forEach((dir) => { + if (dir === d) { + return; + } - this.directives.forEach((dir) => { - if (dir === directive) { - return; - } + dir.open.set(false); + dir.tuiAccordion = false; + dir.tuiAccordionChange.emit(false); + }); + } - dir.open.set(false); - dir.tuiAccordionChange.emit(false); - }); - } + this.expands.get(this.directives.toArray().indexOf(d))!.expanded = d.open(); + }); + } - this.expands.get(this.directives.toArray().indexOf(directive))!.expanded = value; + public toggle(directive: TuiAccordionDirective): void { + this.toggle$.next(directive); } } diff --git a/projects/experimental/components/accordion/accordion.directive.ts b/projects/experimental/components/accordion/accordion.directive.ts index 96ee6d2c0b88..2cf49ecd029d 100644 --- a/projects/experimental/components/accordion/accordion.directive.ts +++ b/projects/experimental/components/accordion/accordion.directive.ts @@ -34,12 +34,13 @@ export class TuiAccordionDirective implements OnChanges { public ngOnChanges(): void { this.open.set(!!this.tuiAccordion); - this.accordion.toggle(this, this.open()); + this.accordion.toggle(this); } public toggle(): void { this.open.set(!this.open()); + this.tuiAccordion = this.open(); this.tuiAccordionChange.emit(this.open()); - this.accordion.toggle(this, this.open()); + this.accordion.toggle(this); } } diff --git a/projects/experimental/components/expand/expand.component.ts b/projects/experimental/components/expand/expand.component.ts index a33f60d49a82..e4144661491d 100644 --- a/projects/experimental/components/expand/expand.component.ts +++ b/projects/experimental/components/expand/expand.component.ts @@ -1,12 +1,15 @@ import {NgIf, NgTemplateOutlet} from '@angular/common'; import { ChangeDetectionStrategy, + ChangeDetectorRef, Component, ContentChild, + inject, Input, signal, TemplateRef, } from '@angular/core'; +import {tuiInjectElement} from '@taiga-ui/cdk'; import {TuiItem} from '@taiga-ui/cdk/directives/item'; @Component({ @@ -30,6 +33,9 @@ import {TuiItem} from '@taiga-ui/cdk/directives/item'; }, }) export class TuiExpand { + private readonly el = tuiInjectElement(); + private readonly cdr = inject(ChangeDetectorRef); + @ContentChild(TuiItem, {read: TemplateRef}) protected content?: TemplateRef; @@ -38,7 +44,14 @@ export class TuiExpand { @Input() public set expanded(expanded: boolean) { + if (expanded === this.signal()) { + return; + } + this.signal.set(expanded); + // TODO: try removing in Angular 17 + this.cdr.detectChanges(); + this.el.classList.toggle('_expanded', expanded); } protected onTransitionEnd({propertyName}: TransitionEvent): void { From 9bb70fdfef6e97716652e2eda5b3b3103b65511f Mon Sep 17 00:00:00 2001 From: waterplea Date: Sat, 18 Jan 2025 13:35:33 +0400 Subject: [PATCH 2/3] chore: fix --- .../experimental/components/accordion/accordion.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/experimental/components/accordion/accordion.component.ts b/projects/experimental/components/accordion/accordion.component.ts index 17b010d13c07..eb3d0eb04448 100644 --- a/projects/experimental/components/accordion/accordion.component.ts +++ b/projects/experimental/components/accordion/accordion.component.ts @@ -39,7 +39,7 @@ import {TuiAccordionDirective} from './accordion.directive'; }) export class TuiAccordionComponent implements AfterViewInit { private readonly destroyRef = inject(DestroyRef); - private readonly toggle$ = new ReplaySubject(); + private readonly toggle$ = new ReplaySubject(Infinity); @ContentChildren(TuiExpand) public readonly expands: QueryList = EMPTY_QUERY; From 222c25dc1deaa04199102b1fd1f95ee69b398271 Mon Sep 17 00:00:00 2001 From: taiga-family-bot Date: Sat, 18 Jan 2025 09:43:18 +0000 Subject: [PATCH 3/3] chore: apply changes after linting [bot] --- .../demo/src/modules/components/accordion/examples/1/index.ts | 2 +- .../experimental/components/accordion/accordion.component.ts | 3 +-- projects/experimental/components/expand/expand.component.ts | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/projects/demo/src/modules/components/accordion/examples/1/index.ts b/projects/demo/src/modules/components/accordion/examples/1/index.ts index e1b45ec57686..2cb806b86bbf 100644 --- a/projects/demo/src/modules/components/accordion/examples/1/index.ts +++ b/projects/demo/src/modules/components/accordion/examples/1/index.ts @@ -6,7 +6,7 @@ import {TuiAccordion} from '@taiga-ui/experimental'; @Component({ standalone: true, - imports: [TuiAccordion, NgForOf, KeyValuePipe], + imports: [KeyValuePipe, NgForOf, TuiAccordion], templateUrl: './index.html', encapsulation, changeDetection, diff --git a/projects/experimental/components/accordion/accordion.component.ts b/projects/experimental/components/accordion/accordion.component.ts index eb3d0eb04448..1b38fe7fdc0a 100644 --- a/projects/experimental/components/accordion/accordion.component.ts +++ b/projects/experimental/components/accordion/accordion.component.ts @@ -1,12 +1,11 @@ +import type {AfterViewInit, QueryList} from '@angular/core'; import { - type AfterViewInit, ChangeDetectionStrategy, Component, ContentChildren, DestroyRef, inject, Input, - type QueryList, signal, ViewEncapsulation, } from '@angular/core'; diff --git a/projects/experimental/components/expand/expand.component.ts b/projects/experimental/components/expand/expand.component.ts index e4144661491d..95947674cd0b 100644 --- a/projects/experimental/components/expand/expand.component.ts +++ b/projects/experimental/components/expand/expand.component.ts @@ -9,8 +9,8 @@ import { signal, TemplateRef, } from '@angular/core'; -import {tuiInjectElement} from '@taiga-ui/cdk'; import {TuiItem} from '@taiga-ui/cdk/directives/item'; +import {tuiInjectElement} from '@taiga-ui/cdk/utils/dom'; @Component({ standalone: true,