Skip to content

Commit 196ba3e

Browse files
jcorrea97alinelariguet
authored andcommitted
feat(search): implementa modo trigger no componente
Implementa modo trigger no componente, ativando a busca via `enter` ou `click` no ícone fixes DTHFUI-7809
1 parent bc4c627 commit 196ba3e

File tree

8 files changed

+115
-97
lines changed

8 files changed

+115
-97
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@ describe('PoSearchBaseComponent', () => {
1717

1818
describe('Properties:', () => {
1919
it('label: should set label when is setted', () => {
20+
component['language'] = 'en';
2021
component.ariaLabel = 'Search';
2122

2223
expect(component.ariaLabel).toBe('Search');
2324
});
2425

2526
it('label: should concat label with literals', () => {
27+
component['language'] = 'en';
2628
component.ariaLabel = 'label button';
2729
expect(component.ariaLabel).toBe('label button Search');
2830
});

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

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { PoSearchLiterals } from './literals/po-search-literals';
77
import { poSearchLiteralsDefault } from './literals/po-search-literals-default';
88
import { PoSearchFilterMode } from './enum/po-search-filter-mode.enum';
99

10+
export type searchMode = 'action' | 'trigger';
1011
/**
1112
* @description
1213
*
@@ -83,8 +84,6 @@ export class PoSearchBaseComponent {
8384
}
8485

8586
/**
86-
* @optional
87-
*
8887
* @description
8988
*
9089
* Deve ser informado o nome da propriedade do objeto que será utilizado para a conversão dos itens apresentados na lista do componente (p-items), esta propriedade será responsável pelo texto de apresentação de cada item da lista.
@@ -100,6 +99,21 @@ export class PoSearchBaseComponent {
10099
*/
101100
@Input('p-icon') icon: string | TemplateRef<void>;
102101

102+
/**
103+
* @optional
104+
*
105+
* @description
106+
*
107+
* Determina a forma de realizar a pesquisa no componente
108+
*
109+
* Valores aceitos:
110+
* - `action`: Realiza a busca a cada caractere digitado.
111+
* - `trigger`: Realiza a busca ao pressionar `enter` ou clicar no ícone de busca.
112+
*
113+
* @default `action`
114+
*/
115+
@Input('p-search-type') type: searchMode = 'action';
116+
103117
/**
104118
* @optional
105119
*
Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,43 @@
11
<div class="po-search" [class.po-search-disabled]="disabled">
2-
<div class="po-search-icon">
2+
<div *ngIf="type === 'action'" class="po-search-icon">
33
<po-icon [p-icon]="icon ? icon : 'po-icon-search'"></po-icon>
44
</div>
55

66
<input
77
#poSearchInput
8-
type="text"
98
class="po-search-input"
9+
type="text"
1010
[ariaLabel]="ariaLabel"
11-
[class.po-search-icon-right]="!!poSearchInput.value && !disabled"
11+
[class.po-search-input-clean]="!!poSearchInput.value && !disabled"
12+
[class.po-search-input-trigger]="type === 'trigger'"
1213
[disabled]="disabled"
1314
[placeholder]="literals.search"
14-
(blur)="onBlur()"
15-
(focus)="onFocus()"
16-
(input)="onSearchChange($event.target.value)"
15+
(input)="onSearchChange($event.target.value, type === 'action' ? true : false)"
16+
(keyup.enter)="onSearchChange($event.target.value, type === 'trigger' ? true : false)"
1717
/>
1818

19-
<div *ngIf="!!poSearchInput.value && !disabled" class="po-search-container-clean">
19+
<div class="po-search-buttons">
2020
<button
21-
class="po-search-clean"
21+
*ngIf="!!poSearchInput.value && !disabled"
22+
class="po-search-button po-search-button-clean"
23+
type="button"
2224
[ariaLabel]="literals.clean"
2325
(click)="clearSearch()"
2426
(keydown.enter)="clearSearch()"
2527
>
2628
<po-icon p-icon="po-icon-clear-content"></po-icon>
2729
</button>
30+
31+
<button
32+
*ngIf="type === 'trigger'"
33+
class="po-search-button po-search-button-trigger"
34+
type="button"
35+
[ariaLabel]="literals.search"
36+
(click)="onSearchChange(poSearchInput.value, true)"
37+
(keydown.enter)="onSearchChange(poSearchInput.value, true)"
38+
[disabled]="disabled"
39+
>
40+
<po-icon [p-icon]="icon ? icon : 'po-icon-search'"> </po-icon>
41+
</button>
2842
</div>
2943
</div>

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

Lines changed: 9 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ describe('PoSearchComponent', () => {
4545
});
4646

4747
it('onSearchChange: should filter items based on search text and emit filtered items', () => {
48-
component.onSearchChange('text');
48+
component.onSearchChange('text', true);
4949

5050
expect(component.filteredItems).toEqual([{ text: 'Text 1' }, { text: 'Text 2' }]);
5151
expect(component.filteredItemsChange.emit).toHaveBeenCalledWith([{ text: 'Text 1' }, { text: 'Text 2' }]);
@@ -54,7 +54,7 @@ describe('PoSearchComponent', () => {
5454
it('onSearchChange: should filter items based on search text using startsWith', () => {
5555
component.filterType = PoSearchFilterMode.startsWith;
5656

57-
component.onSearchChange('Text');
57+
component.onSearchChange('Text', true);
5858

5959
expect(component.filteredItems).toEqual([{ text: 'Text 1' }, { text: 'Text 2' }]);
6060
expect(component.filteredItemsChange.emit).toHaveBeenCalledWith([{ text: 'Text 1' }, { text: 'Text 2' }]);
@@ -63,14 +63,14 @@ describe('PoSearchComponent', () => {
6363
it('onSearchChange: should filter items based on search text using endsWith', () => {
6464
component.filterType = PoSearchFilterMode.endsWith;
6565

66-
component.onSearchChange('2');
66+
component.onSearchChange('2', true);
6767

6868
expect(component.filteredItems).toEqual([{ text: 'Text 2' }]);
6969
expect(component.filteredItemsChange.emit).toHaveBeenCalledWith([{ text: 'Text 2' }]);
7070
});
7171

7272
it('onSearchChange: should not filter items if search text is empty', () => {
73-
component.onSearchChange('');
73+
component.onSearchChange('', true);
7474

7575
expect(component.filteredItems).toEqual([{ text: 'Text 1' }, { text: 'Text 2' }, { text: 'Other Text' }]);
7676
expect(component.filteredItemsChange.emit).toHaveBeenCalledWith(component.items);
@@ -79,7 +79,7 @@ describe('PoSearchComponent', () => {
7979
it('onSearchChange: should return false if filter mode is not recognized', () => {
8080
component.filterType = ('invalidMode' as unknown) as PoSearchFilterMode;
8181

82-
const result = component.onSearchChange('text');
82+
const result = component.onSearchChange('text', true);
8383

8484
expect(result).toBeFalsy();
8585
expect(component.filteredItems).toEqual([]);
@@ -91,7 +91,7 @@ describe('PoSearchComponent', () => {
9191
component.items = [item];
9292
component.filterKeys = ['value'];
9393

94-
component.onSearchChange('42');
94+
component.onSearchChange('42', true);
9595

9696
expect(component.filteredItems).toEqual([item]);
9797
expect(component.filteredItemsChange.emit).toHaveBeenCalledWith([item]);
@@ -100,7 +100,7 @@ describe('PoSearchComponent', () => {
100100
it('onSearchChange: should filter items based on search text using contains', () => {
101101
component.filterType = PoSearchFilterMode.contains;
102102

103-
component.onSearchChange('ext');
103+
component.onSearchChange('ext', true);
104104

105105
expect(component.filteredItems).toEqual([{ text: 'Text 1' }, { text: 'Text 2' }, { text: 'Other Text' }]);
106106

@@ -117,46 +117,17 @@ describe('PoSearchComponent', () => {
117117
component.filterType = PoSearchFilterMode.contains;
118118
component.items = [{ name: null }];
119119

120-
component.onSearchChange(searchText);
120+
component.onSearchChange(searchText, true);
121121

122122
expect(component.filteredItems.length).toBe(0);
123123
});
124124

125125
it('onSearchChange: should reset filteredItems and emit empty array', () => {
126126
component.items = [];
127127
component.filterKeys = ['name'];
128-
component.onSearchChange('item');
128+
component.onSearchChange('item', true);
129129

130130
expect(component.filteredItems).toEqual([]);
131131
expect(component.filteredItemsChange.emit).toHaveBeenCalledWith([]);
132132
});
133-
134-
it('should remove focused class on blur', () => {
135-
const parentElement = document.createElement('div');
136-
const nativeElement = document.createElement('input');
137-
138-
parentElement.appendChild(nativeElement);
139-
parentElement.classList.add('po-search-focused');
140-
141-
component.poSearchInput = new ElementRef(nativeElement);
142-
component.onBlur();
143-
144-
expect(parentElement.classList.contains('po-search-focused')).toBeFalsy();
145-
});
146-
147-
it('should add focused class on focus', () => {
148-
const parentElement = document.createElement('div');
149-
const nativeElement = document.createElement('input');
150-
parentElement.appendChild(nativeElement);
151-
152-
component.poSearchInput = {
153-
nativeElement: {
154-
parentElement: parentElement
155-
}
156-
} as ElementRef;
157-
158-
component.onFocus();
159-
160-
expect(parentElement.classList.contains('po-search-focused')).toBeTruthy();
161-
});
162133
});

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

Lines changed: 28 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -45,49 +45,43 @@ export class PoSearchComponent extends PoSearchBaseComponent implements OnInit {
4545

4646
clearSearch(): void {
4747
this.poSearchInput.nativeElement.value = '';
48-
this.onSearchChange('');
48+
this.onSearchChange('', true);
4949
this.filteredItemsChange.emit(this.items);
5050
this.poSearchInput.nativeElement.focus();
5151
}
5252

53-
onBlur(): void {
54-
this.renderer.removeClass(this.poSearchInput.nativeElement.parentElement, 'po-search-focused');
55-
}
56-
57-
onFocus(): void {
58-
this.renderer.addClass(this.poSearchInput.nativeElement.parentElement, 'po-search-focused');
59-
}
60-
61-
onSearchChange(searchText: string): void {
62-
searchText = searchText.toLowerCase();
53+
onSearchChange(searchText: string, activated: boolean): void {
54+
if (activated) {
55+
searchText = searchText.toLowerCase();
6356

64-
if (this.items && this.items.length > 0) {
65-
this.filteredItems = this.items.filter(item =>
66-
this.filterKeys.some(key => {
67-
let value = item[key];
57+
if (this.items && this.items.length > 0) {
58+
this.filteredItems = this.items.filter(item =>
59+
this.filterKeys.some(key => {
60+
let value = item[key];
6861

69-
if (typeof value !== 'string') {
70-
value = value != null ? value.toString() : null;
71-
}
62+
if (typeof value !== 'string') {
63+
value = value != null ? value.toString() : null;
64+
}
7265

73-
value = value != null ? value.toLowerCase() : null;
66+
value = value != null ? value.toLowerCase() : null;
7467

75-
if (this.filterType === PoSearchFilterMode.startsWith) {
76-
return value != null && value.startsWith(searchText);
77-
} else if (this.filterType === PoSearchFilterMode.contains) {
78-
return value != null && value.includes(searchText);
79-
} else if (this.filterType === PoSearchFilterMode.endsWith) {
80-
return value != null && value.endsWith(searchText);
81-
}
68+
if (this.filterType === PoSearchFilterMode.startsWith) {
69+
return value != null && value.startsWith(searchText);
70+
} else if (this.filterType === PoSearchFilterMode.contains) {
71+
return value != null && value.includes(searchText);
72+
} else if (this.filterType === PoSearchFilterMode.endsWith) {
73+
return value != null && value.endsWith(searchText);
74+
}
8275

83-
return false;
84-
})
85-
);
86-
this.filteredItemsChange.emit(this.filteredItems);
87-
} else {
88-
this.filteredItems = [];
89-
this.filteredItemsChange.emit(this.filteredItems);
76+
return false;
77+
})
78+
);
79+
this.filteredItemsChange.emit(this.filteredItems);
80+
} else {
81+
this.filteredItems = [];
82+
this.filteredItemsChange.emit(this.filteredItems);
83+
}
84+
this.changeModel.emit(searchText);
9085
}
91-
this.changeModel.emit(searchText);
9286
}
9387
}

projects/ui/src/lib/components/po-search/po-search.module.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@ import { PoIconModule } from '../po-icon';
55
import { PoLoadingModule } from '../po-loading';
66
import { PoSearchComponent } from './po-search.component';
77
import { FormsModule } from '@angular/forms';
8+
import { PoAccordionModule } from '../po-accordion/po-accordion.module';
89

910
/**
1011
* @description
1112
*
1213
* Módulo do componente po-search.
1314
*/
1415
@NgModule({
15-
imports: [CommonModule, PoCleanModule, PoIconModule, PoLoadingModule, FormsModule],
16+
imports: [CommonModule, PoCleanModule, PoIconModule, PoLoadingModule, PoAccordionModule, FormsModule],
1617
declarations: [PoSearchComponent],
1718
exports: [PoSearchComponent]
1819
})

projects/ui/src/lib/components/po-search/samples/sample-po-search-labs/sample-po-search-labs.component.html

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,29 @@
99
[p-filter-keys]="fieldKeys"
1010
[p-literals]="customLiterals"
1111
[p-filter-type]="filterMode"
12+
[p-search-type]="searchMode"
1213
(p-filtered-items-change)="filter($event)"
1314
(p-change-model)="changeModel($event)"
1415
></po-search>
1516
</div>
1617

1718
<hr />
1819
<div class="po-row">
19-
<po-widget class="po-md-12">
20-
<ul class="po-md-12 row">
21-
<li *ngFor="let item of filteredItems">
22-
<ng-container *ngFor="let key of changeFilter(item)">
23-
<div>
24-
<strong>{{ key }}: </strong> {{ item[key] }} &nbsp;
25-
</div>
26-
</ng-container>
27-
</li>
28-
</ul>
29-
</po-widget>
20+
<po-accordion class="po-md-12">
21+
<po-accordion-item p-label="Itens encontrados: {{ filteredItems.length }}">
22+
<po-widget class="po-md-12">
23+
<ul class="sample-list-search po-md-12 row">
24+
<li *ngFor="let item of filteredItems">
25+
<ng-container *ngFor="let key of changeFilter(item)">
26+
<div>
27+
<strong>{{ key }}: </strong> {{ item[key] }} &nbsp;
28+
</div>
29+
</ng-container>
30+
</li>
31+
</ul>
32+
</po-widget>
33+
</po-accordion-item>
34+
</po-accordion>
3035
</div>
3136
<hr />
3237

@@ -103,6 +108,16 @@
103108
[p-options]="filterModeOptions"
104109
>
105110
</po-radio-group>
111+
112+
<po-radio-group
113+
class="po-md-6 po-lg-4"
114+
name="searchMode"
115+
[(ngModel)]="searchMode"
116+
p-columns="1"
117+
p-label="Search Mode"
118+
[p-options]="searchModeOptions"
119+
>
120+
</po-radio-group>
106121
</div>
107122

108123
<hr />

0 commit comments

Comments
 (0)