Skip to content

Commit

Permalink
refactor(accordion): introducing signals signals
Browse files Browse the repository at this point in the history
  • Loading branch information
lexasq committed Nov 4, 2024
1 parent f09e4b1 commit b606d45
Show file tree
Hide file tree
Showing 13 changed files with 59 additions and 49 deletions.
6 changes: 4 additions & 2 deletions libs/doc-pages/accordion/src/lib/demos/animated/animated.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { Component } from '@angular/core';
import { ChangeDetectionStrategy, Component } from '@angular/core';

@Component({
// eslint-disable-next-line @angular-eslint/component-selector
selector: 'demo-accordion-animation',
templateUrl: './animated.html'
templateUrl: './animated.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class DemoAccordionAnimatedComponent {}

2 changes: 1 addition & 1 deletion libs/doc-pages/accordion/src/lib/demos/basic/basic.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<accordion>
<accordion [isAnimated]="false">
<accordion-group heading="Static Header">
This content is straight in the template.
</accordion-group>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<accordion>
<accordion [isAnimated]="false">
<accordion-group>
<button
class="btn btn-link btn-block justify-content-between d-flex w-100 shadow-none"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
</button>
</p>

<accordion>
<accordion [isAnimated]="false">
<accordion-group heading="Static Header"
[isDisabled]="isFirstDisabled">
This content is straight in the template.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
</button>
</p>

<accordion>
<accordion [isAnimated]="false">
<accordion-group *ngFor="let group of groups" [heading]="group.title">
{{ group?.content }}
</accordion-group>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<accordion>
<accordion [isAnimated]="false">
<accordion-group heading="Dynamic Body Content">
<p>The body of the accordion group grows to fit the contents</p>
<button type="button" class="btn btn-primary btn-sm" (click)="addItem()">Add
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
</button>
</p>

<accordion>
<accordion [isAnimated]="false">
<accordion-group heading="Content 1">
<p>accordion 1</p>
</accordion-group>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<accordion>
<accordion [isAnimated]="false">
<accordion-group heading="Group without isOpenChange event listener">
<p>Some content</p>
</accordion-group>
Expand Down
2 changes: 1 addition & 1 deletion libs/doc-pages/accordion/src/lib/demos/opened/opened.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<accordion>
<accordion [isAnimated]="false">
<accordion-group heading="Content 1">
<p>accordion 1</p>
</accordion-group>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<accordion>
<accordion [isAnimated]="false">
<accordion-group heading="Static Header, initially expanded"
[panelClass]="customClass"
[isOpen]="isFirstOpen">
Expand Down
12 changes: 6 additions & 6 deletions src/accordion/accordion-group.component.html
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
<div class="panel card" [ngClass]="panelClass">
<div class="panel card" [ngClass]="panelClass()">
<div
class="panel-heading card-header"
role="tab"
(click)="toggleOpen()"
[ngClass]="isDisabled ? 'panel-disabled' : 'panel-enabled'"
[ngClass]="isDisabled() ? 'panel-disabled' : 'panel-enabled'"
>
<div class="panel-title">
<div role="button" class="accordion-toggle" [attr.aria-expanded]="isOpen">
<button class="btn btn-link" *ngIf="heading" [ngClass]="{ 'text-muted': isDisabled }" type="button">
{{ heading }}
<div role="button" class="accordion-toggle" [attr.aria-expanded]="isOpen()">
<button class="btn btn-link" *ngIf="heading()" [ngClass]="{ 'text-muted': isDisabled() }" type="button">
{{ heading() }}
</button>
<ng-content select="[accordion-heading]"></ng-content>
</div>
</div>
</div>
<div class="panel-collapse collapse" role="tabpanel" [collapse]="!isOpen" [isAnimated]="isAnimated">
<div class="panel-collapse collapse" role="tabpanel" [collapse]="!isOpen()" [isAnimated]="isAnimated">
<div class="panel-body card-block card-body">
<ng-content></ng-content>
</div>
Expand Down
42 changes: 18 additions & 24 deletions src/accordion/accordion-group.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {
Component, HostBinding, Inject, Input, OnDestroy, OnInit, Output, EventEmitter
Component, HostBinding, Inject, OnDestroy, OnInit, input, output, model
} from '@angular/core';
import { AccordionComponent } from './accordion.component';
import { CollapseModule } from 'ngx-bootstrap/collapse';
Expand Down Expand Up @@ -27,44 +27,38 @@ export class AccordionPanelComponent implements OnInit, OnDestroy {
/** turn on/off animation */
isAnimated = false;
/** Clickable text in accordion's group header, check `accordion heading` below for using html in header */
@Input() heading!: string;
public heading = input<string>();
/** Provides an ability to use Bootstrap's contextual panel classes
* (`panel-primary`, `panel-success`, `panel-info`, etc...).
* List of all available classes [available here]
* (https://getbootstrap.com/docs/3.3/components/#panels-alternatives)
*/
@Input() panelClass = 'panel-default';
public panelClass = input<string>('panel-default');
/** if <code>true</code> — disables accordion group */
@Input() isDisabled = false;
public isDisabled = input<boolean>(false);
/** Emits when the opened state changes */
@Output() isOpenChange: EventEmitter<boolean> = new EventEmitter();
public isOpenChange = output<boolean>();

// Questionable, maybe .panel-open should be on child div.panel element?
/** Is accordion group open or closed. This property supports two-way binding */
@HostBinding('class.panel-open')
@Input()
get isOpen(): boolean {
return this._isOpen;
}

set isOpen(value: boolean) {
if (value !== this.isOpen) {
if (value) {
this.accordion.closeOtherPanels(this);
}
this._isOpen = value;
Promise.resolve(null)
.then(() => {
this.isOpenChange.emit(value);
});
}
}
public isOpen = model<boolean>(false);

protected _isOpen = false;
protected accordion: AccordionComponent;

constructor(@Inject(AccordionComponent) accordion: AccordionComponent) {
this.accordion = accordion;

this.isOpen.subscribe((value) => {
if (value !== this._isOpen) {
if (value) {
this.accordion.closeOtherPanels(this);
}
this._isOpen = value;
this.isOpenChange.emit(value);
}
});
}

ngOnInit(): void {
Expand All @@ -76,8 +70,8 @@ export class AccordionPanelComponent implements OnInit, OnDestroy {
}

toggleOpen(): void {
if (!this.isDisabled) {
this.isOpen = !this.isOpen;
if (!this.isDisabled()) {
this.isOpen.set(!this.isOpen());
}
}
}
30 changes: 22 additions & 8 deletions src/accordion/accordion.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, Input } from '@angular/core';
import { Component, input, OnChanges, SimpleChanges } from '@angular/core';
import { AccordionPanelComponent } from './accordion-group.component';
import { AccordionConfig } from './accordion.config';

Expand All @@ -8,39 +8,53 @@ import { AccordionConfig } from './accordion.config';
template: `<ng-content></ng-content>`,
// eslint-disable-next-line @angular-eslint/no-host-metadata-property
host: {
'[attr.aria-multiselectable]': 'closeOthers',
'[attr.aria-multiselectable]': '_closeOthers',
role: 'tablist',
class: 'panel-group',
style: 'display: block'
},
standalone: true
})
export class AccordionComponent {
export class AccordionComponent implements OnChanges {
/** turn on/off animation */
@Input() isAnimated = false;
isAnimated = input<boolean>(false);
_isAnimated = this.isAnimated();

/** if `true` expanding one item will close all others */
@Input() closeOthers = false;
closeOthers = input<boolean>(false);
_closeOthers = this.closeOthers();

protected groups: AccordionPanelComponent[] = [];

constructor(config: AccordionConfig) {
Object.assign(this, config);
}

ngOnChanges(changes: SimpleChanges) {
if (changes['isAnimated'] && !changes['isAnimated'].firstChange) {
// Only update if foo has changed and isn't the initial setup
this._isAnimated = this.isAnimated();
}
if (changes['closeOthers'] && !changes['closeOthers'].firstChange) {
// Only update if foo has changed and isn't the initial setup
this._closeOthers = this.closeOthers();
}
}

closeOtherPanels(openGroup: AccordionPanelComponent): void {
if (!this.closeOthers) {
if (!this._closeOthers) {
return;
}

this.groups.forEach((group: AccordionPanelComponent) => {
if (group !== openGroup) {
group.isOpen = false;
group.isOpen.set(false);
}
});
}

addGroup(group: AccordionPanelComponent): void {
group.isAnimated = this.isAnimated;
group.isAnimated = this._isAnimated;
this.groups.push(group);
}

Expand Down

0 comments on commit b606d45

Please sign in to comment.