Last active
June 13, 2017 14:07
-
-
Save masimplo/8527b8b0017debb291654a7c6f124bc2 to your computer and use it in GitHub Desktop.
Accordion component for Ionic
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { AccordionTabComponent } from './accordion-tab.component'; | |
| import { AccordionComponent } from './accordion.component'; | |
| describe('AccordionTab::Component', function () { | |
| let accordionComponent: AccordionComponent; | |
| let sut: AccordionTabComponent; | |
| beforeEach(function () { | |
| accordionComponent = new AccordionComponent(); | |
| sut = new AccordionTabComponent(accordionComponent); | |
| }); | |
| it('can be instantiated', function () { | |
| expect(sut).toBeDefined(); | |
| }); | |
| it('adds itself to the parent component', () => { | |
| expect(sut.accordion.tabCount).toEqual(1); | |
| }); | |
| it('emits selected event when select is called', (done) => { | |
| sut.selectedChanged | |
| .subscribe(({selected, index}) => { | |
| expect(selected).toEqual(true); | |
| expect(index).toEqual(0); | |
| done(); | |
| }); | |
| sut.select(new Event('click')); | |
| }); | |
| it('does not emit selected event when select is called but control is disabled', () => { | |
| spyOn(sut.selectedChanged, 'emit'); | |
| sut.disabled = true; | |
| sut.select(new Event('click')); | |
| expect(sut.selectedChanged.emit).not.toHaveBeenCalled(); | |
| }); | |
| it('does not emit selected event when select is called but control is already selected', () => { | |
| spyOn(sut.selectedChanged, 'emit'); | |
| sut.selected = true; | |
| sut.select(new Event('click')); | |
| expect(sut.selectedChanged.emit).not.toHaveBeenCalled(); | |
| }); | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { Input, EventEmitter, Output, Component, HostBinding } from '@angular/core'; | |
| import { AccordionComponent } from './accordion.component'; | |
| @Component({ | |
| selector: 'cv-accordion-tab', | |
| templateUrl: 'accordion-tab.html' | |
| }) | |
| export class AccordionTabComponent { | |
| @HostBinding('class.selected') | |
| @Input() | |
| selected: boolean; | |
| @Input() disabled: boolean; | |
| @Output() selectedChanged: EventEmitter<any> = new EventEmitter(); | |
| public tabIndex = -1; | |
| constructor(public accordion?: AccordionComponent) { | |
| if (accordion) { | |
| this.tabIndex = this.accordion.addTab(this); | |
| } | |
| } | |
| public select(event: Event) { | |
| if (this.disabled || this.selected) return; | |
| this.selected = true; | |
| this.selectedChanged.emit({ selected: this.selected, index: this.tabIndex }); | |
| event.preventDefault(); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <div class="tab-header" (click)="select($event)" [class.selected]="selected"> | |
| <ng-content select="[tab-header]"></ng-content> | |
| <ion-icon class="icon-dropdown-mini"></ion-icon> | |
| </div> | |
| <div class="container" [class.selected]="selected"> | |
| <div *ngIf="selected" class="content"> | |
| <ng-content select="[tab-content]"></ng-content> | |
| </div> | |
| </div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| .ios, .md { | |
| cv-accordion-tab { | |
| display: flex; | |
| flex-direction: column; | |
| flex-shrink: 0; | |
| .tab-header { | |
| display:flex; | |
| min-height: 40px; | |
| border-bottom: solid 1px #ddd; | |
| background-color: #eee; | |
| justify-content: center; | |
| align-items: center; | |
| h2{ | |
| margin: 0; | |
| } | |
| } | |
| .content { | |
| background-color: #fff; | |
| } | |
| .container { | |
| background-color: #fff; | |
| .list{ | |
| margin:0; | |
| } | |
| } | |
| .container.selected { | |
| overflow-y: scroll; | |
| border-bottom: solid 1px #ddd; | |
| flex-grow: 1; | |
| flex-basis: 0; | |
| } | |
| ion-icon.icon-dropdown-mini { | |
| height: 17px; | |
| margin: 5px 10px; | |
| transition: all 0.2s ease-in-out; | |
| color: #999; | |
| } | |
| .selected ion-icon.icon-dropdown-mini { | |
| transition: all 0.2s ease-in-out; | |
| transform: rotateX(-180deg); | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { AccordionComponent } from './accordion.component'; | |
| import { AccordionTabComponent } from './accordion-tab.component'; | |
| describe('Accordion::Component', function () { | |
| let sut: AccordionComponent; | |
| beforeEach(function () { | |
| sut = new AccordionComponent(); | |
| }); | |
| it('can be instantiated', function () { | |
| expect(sut).toBeDefined(); | |
| }); | |
| it('holds added accordion tabs', function () { | |
| expect(sut.tabCount).toEqual(0); | |
| // tslint:disable-next-line:no-unused-expression | |
| new AccordionTabComponent(sut); | |
| expect(sut.tabCount).toEqual(1); | |
| }); | |
| it('closes all other tabs when a tab emits selected event', function () { | |
| const tab1 = new AccordionTabComponent(sut); | |
| const tab2 = new AccordionTabComponent(sut); | |
| const tab3 = new AccordionTabComponent(sut); | |
| tab2.select(new Event('click')); | |
| expect(tab1.selected).toEqual(false); | |
| expect(tab2.selected).toEqual(true); | |
| expect(tab3.selected).toEqual(false); | |
| tab1.select(new Event('click')); | |
| expect(tab1.selected).toEqual(true); | |
| expect(tab2.selected).toEqual(false); | |
| expect(tab3.selected).toEqual(false); | |
| }); | |
| it('clears event emitter and tabs on destroy', function () { | |
| sut.ngOnDestroy(); | |
| expect(sut.onOpen).toBe(null); | |
| expect(() => sut.tabCount).toThrow(); | |
| }); | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { Component, Output, EventEmitter, OnDestroy } from '@angular/core'; | |
| import { AccordionTabComponent } from './accordion-tab.component'; | |
| @Component({ | |
| selector: 'cv-accordion', | |
| templateUrl: 'accordion.html' | |
| }) | |
| export class AccordionComponent implements OnDestroy { | |
| @Output() public onOpen: EventEmitter<{ index: number }> = new EventEmitter(); | |
| private _tabs: AccordionTabComponent[] = []; | |
| public get tabCount(): number { | |
| return this._tabs.length; | |
| } | |
| public addTab(tab: AccordionTabComponent) { | |
| this._tabs.push(tab); | |
| tab.selectedChanged | |
| .subscribe(({ index }) => { | |
| this._tabs | |
| .filter(t => t.tabIndex !== index) | |
| .forEach(t => { t.selected = false; }); | |
| this.onOpen.emit({ index }); | |
| }); | |
| return this._tabs.length - 1; | |
| } | |
| public ngOnDestroy() { | |
| this._tabs = null; | |
| this.onOpen = null; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <div> | |
| <ng-content></ng-content> | |
| </div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| .md, .ios { | |
| cv-accordion { | |
| height: 100%; | |
| >div { | |
| display: flex; | |
| flex-direction: column; | |
| height: 100%; | |
| cv-accordion-tab.selected{ | |
| transition: flex-grow 0.2s linear; | |
| flex-grow: 1; | |
| } | |
| cv-accordion-tab{ | |
| transition: flex-grow 0.2s linear; | |
| } | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <cv-accordion> | |
| <cv-accordion-tab selected="true"> | |
| <h2 tab-header class="text-uppercase">Title</h2> | |
| <ion-list tab-content> | |
| <div>My content</div> | |
| </ion-list> | |
| </cv-accordion-tab> | |
| <cv-accordion-tab"> | |
| <h2 tab-header class="text-uppercase">Another Title</h2> | |
| <ion-list tab-content> | |
| <div>My content 2</div> | |
| </ion-list> | |
| </cv-accordion-tab> | |
| </cv-accordion> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment