Skip to content

Commit 8536326

Browse files
feat(tabs): adiciona output p-actived-tab e o método activateTab
1 parent 1a9c777 commit 8536326

File tree

4 files changed

+113
-6
lines changed

4 files changed

+113
-6
lines changed

projects/ui/src/lib/components/po-tabs/po-tab/po-tab-base.component.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { EventEmitter, Input, Output, Directive } from '@angular/core';
1+
import { EventEmitter, Input, Output, Directive, output } from '@angular/core';
22

33
import { convertToBoolean, uuid } from '../../../utils/util';
44

@@ -30,6 +30,9 @@ export abstract class PoTabBaseComponent {
3030
*/
3131
@Input({ alias: 'p-hide-close', transform: convertToBoolean }) hideClose: boolean = false;
3232

33+
/** ID da Tab */
34+
@Input('id') id: string = uuid();
35+
3336
/** Método disparado ao clicar na aba. */
3437
@Output('p-click') click = new EventEmitter();
3538

@@ -45,8 +48,15 @@ export abstract class PoTabBaseComponent {
4548
*/
4649
@Output('p-close-tab') closeTab = new EventEmitter();
4750

48-
// ID da aba
49-
id?: string = uuid();
51+
/**
52+
* @optional
53+
*
54+
* @description
55+
*
56+
* Evento emitido quando a aba é ativada.
57+
* Emite a instância do componente da aba que foi ativada.
58+
*/
59+
activatedTab = output<PoTabBaseComponent>({ alias: 'p-activated-tab' });
5060

5161
private _active?: boolean = false;
5262
private _disabled?: boolean = false;

projects/ui/src/lib/components/po-tabs/po-tab/po-tab.base.component.spec.ts

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,27 @@
1-
import { Directive } from '@angular/core';
1+
import { Component } from '@angular/core';
2+
import { TestBed } from '@angular/core/testing';
23

34
import { expectPropertiesValues } from '../../../util-test/util-expect.spec';
45

56
import { PoTabBaseComponent } from './po-tab-base.component';
67

7-
@Directive()
8+
@Component({
9+
template: '',
10+
standalone: true
11+
})
812
class PoTabComponent extends PoTabBaseComponent {
913
setDisplayOnActive() {}
1014
}
1115

1216
describe('PoTabBaseComponent', () => {
13-
const component: PoTabComponent = new PoTabComponent();
17+
let component: PoTabComponent;
18+
19+
beforeEach(async () => {
20+
await TestBed.configureTestingModule({
21+
imports: [PoTabComponent]
22+
}).compileComponents();
23+
component = TestBed.runInInjectionContext(() => new PoTabComponent());
24+
});
1425

1526
it('should be created', () => {
1627
expect(component).toBeTruthy();
@@ -61,5 +72,27 @@ describe('PoTabBaseComponent', () => {
6172

6273
expectPropertiesValues(component, 'hide', invalidValues, expectedReturnFalse);
6374
});
75+
76+
it('id: should have a default value generated by uuid', () => {
77+
expect(component.id).toBeTruthy();
78+
expect(typeof component.id).toBe('string');
79+
expect(component.id.length).toBeGreaterThan(0);
80+
});
81+
82+
it('id: should accept a custom value via input', () => {
83+
component.id = 'custom-tab-id';
84+
expect(component.id).toBe('custom-tab-id');
85+
});
86+
87+
it('activatedTab: should be defined', () => {
88+
expect(component.activatedTab).toBeTruthy();
89+
});
90+
91+
it('activatedTab: should emit the component instance', () => {
92+
spyOn(component.activatedTab, 'emit');
93+
component.activatedTab.emit(component);
94+
95+
expect(component.activatedTab.emit).toHaveBeenCalledWith(component);
96+
});
6497
});
6598
});

projects/ui/src/lib/components/po-tabs/po-tabs.component.spec.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ describe('PoTabsComponent:', () => {
109109

110110
it('onTabActive: should set `previousActiveTab` and call `deactivateTab`', () => {
111111
component['previousActiveTab'] = undefined;
112+
defaultTab.activatedTab = { emit: () => {} };
113+
activeTab.activatedTab = { emit: () => {} };
112114
component.tabsChildren = <any>[defaultTab, activeTab];
113115
const tab = component.tabsChildren[0];
114116

@@ -514,6 +516,7 @@ describe('PoTabsComponent:', () => {
514516
it('onTabActiveByDropdown: should correctly call methods and update styles when called', () => {
515517
const tabMock = jasmine.createSpyObj('PoTabComponent', ['id'], { id: 'tab-id' });
516518
tabMock.click = { emit: () => {} };
519+
tabMock.activatedTab = { emit: () => {} };
517520
component.defaultLastTabWidth = 100;
518521

519522
const nativeElementMock = { style: { width: '' }, getBoundingClientRect: () => ({ width: 100 }) };
@@ -706,5 +709,38 @@ describe('PoTabsComponent:', () => {
706709

707710
expect(lastTabs.widthButton).toBe(200);
708711
});
712+
713+
describe('activateTab', () => {
714+
it('should call selectedTab when the tab id is found in the array', () => {
715+
const mockTab = { id: 'tab-perfil', title: 'Perfil' };
716+
const mockTabsArray = [{ id: 'tab-home', title: 'Home' }, mockTab];
717+
718+
Object.defineProperty(component, 'tabsChildrenArray', {
719+
get: () => mockTabsArray,
720+
configurable: true
721+
});
722+
723+
const spySelectedTab = spyOn(component, 'selectedTab');
724+
725+
component.activateTab('tab-perfil');
726+
727+
expect(spySelectedTab).toHaveBeenCalledWith(mockTab);
728+
});
729+
730+
it('should not call selectedTab if the id does not exist in the array', () => {
731+
const mockTabsArray = [{ id: 'tab-home' }];
732+
733+
Object.defineProperty(component, 'tabsChildrenArray', {
734+
get: () => mockTabsArray,
735+
configurable: true
736+
});
737+
738+
const spySelectedTab = spyOn(component, 'selectedTab');
739+
740+
component.activateTab('id-inexistente');
741+
742+
expect(spySelectedTab).not.toHaveBeenCalled();
743+
});
744+
});
709745
});
710746
});

projects/ui/src/lib/components/po-tabs/po-tabs.component.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ export class PoTabsComponent extends PoTabsBaseComponent implements OnInit, Afte
216216
// Função disparada quando alguma tab ficar ativa
217217
onTabActive(tab: PoTabComponent) {
218218
this.previousActiveTab = this.tabsChildren.find(tabChild => tabChild.active && tabChild.id !== tab.id);
219+
tab.activatedTab.emit(tab);
219220
this.deactivateTab();
220221
}
221222

@@ -500,4 +501,31 @@ export class PoTabsComponent extends PoTabsBaseComponent implements OnInit, Afte
500501
this.setTabIndex(tabRemoveElements[0], 0);
501502
}
502503
}
504+
505+
/**
506+
* Ativa a aba correspondente ao `id` informado.
507+
*
508+
* Para utilizá-la é necessário ter a instância do componente no DOM, podendo ser utilizado o ViewChild da seguinte forma:
509+
*
510+
* ```
511+
* import { PoTabsComponent } from '@po-ui/ng-components';
512+
*
513+
* ...
514+
*
515+
* @ViewChild('poTab', { static: true }) poTab: PoTabsComponent;
516+
*
517+
* focusOnTab() {
518+
* this.poTab.activateTab('meu-id-da-aba');
519+
* }
520+
* ```
521+
*
522+
* @param id Identificador único da aba a ser ativada.
523+
*/
524+
public activateTab(id: string) {
525+
const tab = this.tabsChildrenArray.find(x => x.id === id);
526+
527+
if (tab) {
528+
this.selectedTab(tab);
529+
}
530+
}
503531
}

0 commit comments

Comments
 (0)