diff --git a/projects/templates/src/lib/components/po-page-dynamic-search/po-page-dynamic-search-base.component.spec.ts b/projects/templates/src/lib/components/po-page-dynamic-search/po-page-dynamic-search-base.component.spec.ts
index e40457f077..8d650644f9 100644
--- a/projects/templates/src/lib/components/po-page-dynamic-search/po-page-dynamic-search-base.component.spec.ts
+++ b/projects/templates/src/lib/components/po-page-dynamic-search/po-page-dynamic-search-base.component.spec.ts
@@ -183,4 +183,26 @@ describe('PoPageDynamicSearchBaseComponent:', () => {
expect(component.advancedFilterLiterals).toEqual(expectedValue);
});
});
+
+ describe('p-visible-fixed-filters:', () => {
+ it('should update `_visibleFixedFilters` when `visibleFixedFilters` is set', () => {
+ component.visibleFixedFilters = true;
+ expect(component['_visibleFixedFilters']).toBe(true);
+
+ component.visibleFixedFilters = false;
+ expect(component['_visibleFixedFilters']).toBe(false);
+ });
+
+ it('should return `_visibleFixedFilters` when `visibleFixedFilters` is accessed', () => {
+ component['_visibleFixedFilters'] = true;
+ expect(component.visibleFixedFilters).toBe(true);
+
+ component['_visibleFixedFilters'] = false;
+ expect(component.visibleFixedFilters).toBe(false);
+ });
+
+ it('should have a default value of `true` for `visibleFixedFilters` if not set', () => {
+ expect(component.visibleFixedFilters).toBeTrue();
+ });
+ });
});
diff --git a/projects/templates/src/lib/components/po-page-dynamic-search/po-page-dynamic-search-base.component.ts b/projects/templates/src/lib/components/po-page-dynamic-search/po-page-dynamic-search-base.component.ts
index 6c03109119..8da5688e4e 100644
--- a/projects/templates/src/lib/components/po-page-dynamic-search/po-page-dynamic-search-base.component.ts
+++ b/projects/templates/src/lib/components/po-page-dynamic-search/po-page-dynamic-search-base.component.ts
@@ -154,6 +154,34 @@ export abstract class PoPageDynamicSearchBaseComponent {
*/
@Input('p-quick-search-value') quickSearchValue: string;
+ _visibleFixedFilters = true;
+
+ /**
+ * @optional
+ *
+ * @description
+ *
+ * Controla a visibilidade dos filtros fixos na página.
+ *
+ * - Quando `true` (default), todos os filtros, incluindo os fixos, são exibidos, permitindo que o usuário visualize os filtros aplicados.
+ * - Quando `false`, os filtros fixos são ocultados, não sendo exibidos na interface, mas ainda sendo aplicados como filtros nas requisições.
+ *
+ * Esta propriedade trabalha em conjunto com a propriedade `fixed` dos filtros individuais. Filtros marcados como `fixed: true` não serão exibidos na interface do filtro avançado quando `visibleFixedFilters` for `false`, mas continuarão a ser aplicados de forma transparente ao usuário. Dessa forma, permite-se maior flexibilidade no controle de quais filtros devem ser visíveis ao usuário ou devem ser aplicados permanentemente sem interferência.
+ *
+ * **Exemplo de uso:**
+ * ```html
+ *
+ *
+ * ```
+ */
+ @Input('p-visible-fixed-filters') set visibleFixedFilters(visible: boolean) {
+ this._visibleFixedFilters = visible;
+ }
+
+ get visibleFixedFilters(): boolean {
+ return this._visibleFixedFilters;
+ }
+
/**
* @optional
*
@@ -189,10 +217,10 @@ export abstract class PoPageDynamicSearchBaseComponent {
private _hideCloseDisclaimers: Array = [];
private _literals: PoPageDynamicSearchLiterals;
private _quickSearchWidth: number;
-
- private previousFilters: Array;
private language: string;
+ previousFilters: Array;
+
/**
* @optional
*
@@ -258,12 +286,6 @@ export abstract class PoPageDynamicSearchBaseComponent {
*/
@Input('p-filters') set filters(filters: Array) {
this._filters = Array.isArray(filters) ? [...filters] : [];
-
- if (this.stringify(this._filters) !== this.stringify(this.previousFilters)) {
- this.onChangeFilters(this.filters);
-
- this.previousFilters = [...this._filters];
- }
}
get filters(): Array {
@@ -320,7 +342,7 @@ export abstract class PoPageDynamicSearchBaseComponent {
};
}
- private stringify(columns: Array) {
+ stringify(columns: Array) {
// não faz o stringify da propriedade searchService, pois pode conter objeto complexo e disparar um erro.
return JSON.stringify(columns, (key, value) => {
if (key !== 'searchService') {
diff --git a/projects/templates/src/lib/components/po-page-dynamic-search/po-page-dynamic-search-filters.interface.ts b/projects/templates/src/lib/components/po-page-dynamic-search/po-page-dynamic-search-filters.interface.ts
index 8b7bc0dd15..e825ff9e14 100644
--- a/projects/templates/src/lib/components/po-page-dynamic-search/po-page-dynamic-search-filters.interface.ts
+++ b/projects/templates/src/lib/components/po-page-dynamic-search/po-page-dynamic-search-filters.interface.ts
@@ -12,4 +12,9 @@ export interface PoPageDynamicSearchFilters extends PoDynamicFormField {
* Define um valor inicial para um filtro de busca avançada.
*/
initValue?: any;
+
+ /**
+ * Define um valor fixed para um filtro de busca avançada.
+ */
+ fixed?: boolean;
}
diff --git a/projects/templates/src/lib/components/po-page-dynamic-search/po-page-dynamic-search.component.spec.ts b/projects/templates/src/lib/components/po-page-dynamic-search/po-page-dynamic-search.component.spec.ts
index a93c5d5b5b..a12e553c43 100644
--- a/projects/templates/src/lib/components/po-page-dynamic-search/po-page-dynamic-search.component.spec.ts
+++ b/projects/templates/src/lib/components/po-page-dynamic-search/po-page-dynamic-search.component.spec.ts
@@ -218,17 +218,51 @@ describe('PoPageDynamicSearchComponent:', () => {
const filter = { property: 'value1' };
const optionsService = undefined;
+ const visibleFilters =
+ component.visibleFixedFilters === false
+ ? component.filters.filter(filter => !('fixed' in filter) || !filter.fixed)
+ : component.filters;
+
spyOn(component, 'setDisclaimers');
spyOn(component.advancedSearch, 'emit');
spyOn(component, 'setFilters');
component.onAdvancedSearch({ filter, optionsService });
- expect(component['setDisclaimers']).toHaveBeenCalledWith(filter, optionsService);
+ expect(component['setDisclaimers']).toHaveBeenCalledWith(filter, optionsService, visibleFilters);
expect(component['setFilters']).toHaveBeenCalledBefore(component.advancedSearch.emit);
expect(component.advancedSearch.emit).toHaveBeenCalledWith(filter);
});
+ it('onAdvancedSearch: should correctly filter out fixed filters when visibleFixedFilters is false', () => {
+ component.visibleFixedFilters = false;
+ component.filters = [
+ { property: 'city', fixed: true, initValue: 'Toronto' },
+ { property: 'name', fixed: false, initValue: 'John Doe' },
+ { property: 'country', initValue: 'Canada' }
+ ];
+
+ const filteredItems = { filter: { city: 'Toronto' }, optionsService: undefined };
+
+ const setDisclaimersSpy = spyOn(component as any, 'setDisclaimers').and.callThrough();
+ spyOn(component, 'setFilters').and.callThrough();
+ spyOn(component.advancedSearch, 'emit');
+
+ component.onAdvancedSearch(filteredItems);
+
+ const actualVisibleFilters = setDisclaimersSpy.calls.mostRecent().args[2] as Array;
+
+ expect(actualVisibleFilters.length).toBe(2);
+ expect(actualVisibleFilters).toEqual(
+ jasmine.arrayContaining([
+ jasmine.objectContaining({ property: 'name', fixed: false }),
+ jasmine.objectContaining({ property: 'country' })
+ ])
+ );
+ expect(component['setFilters']).toHaveBeenCalledWith(filteredItems.filter);
+ expect(component.advancedSearch.emit).toHaveBeenCalledWith(filteredItems.filter);
+ });
+
it(`setFilters: should call 'convertToFilters'`, () => {
const filters = [{ property: 'value1' }];
@@ -340,9 +374,40 @@ describe('PoPageDynamicSearchComponent:', () => {
expect(component.changeDisclaimers.emit).toHaveBeenCalledWith(currentDisclaimers);
});
- it(`onRemoveAllDisclaimers: should call 'changeDisclaimers.emit' if all disclaimers are removed`, () => {
+ it(`onRemoveAllDisclaimers: should call 'changeDisclaimers.emit' with disclaimers that need to be kept`, () => {
+ component.filters = [
+ { property: 'status', fixed: true, initValue: 'Ativo', label: 'Status' },
+ { property: 'category', fixed: true, initValue: 'Financeiro', label: 'Categoria' },
+ { property: 'name', fixed: false }
+ ];
+ const expectedDisclaimersToKeep = [
+ {
+ property: 'status',
+ value: 'Ativo',
+ label: 'Status: Ativo',
+ hideClose: true
+ },
+ {
+ property: 'category',
+ value: 'Financeiro',
+ label: 'Categoria: Financeiro',
+ hideClose: true
+ }
+ ];
+
spyOn(component.changeDisclaimers, 'emit');
+ component['onRemoveAllDisclaimers']();
+
+ expect(component.changeDisclaimers.emit).toHaveBeenCalledWith(expectedDisclaimersToKeep);
+ });
+ it(`onRemoveAllDisclaimers: should call 'changeDisclaimers.emit' with an empty array if there are no fixed filters`, () => {
+ component.filters = [
+ { property: 'name', fixed: false, initValue: 'John Doe' },
+ { property: 'age', fixed: false, initValue: 30 }
+ ];
+
+ spyOn(component.changeDisclaimers, 'emit');
component['onRemoveAllDisclaimers']();
expect(component.changeDisclaimers.emit).toHaveBeenCalledWith([]);
@@ -736,6 +801,33 @@ describe('PoPageDynamicSearchComponent:', () => {
expect(component['onAction']).toHaveBeenCalledWith('jhon', true);
});
});
+
+ describe('ngAfterViewInit:', () => {
+ it('should call `onChangeFilters` and update `previousFilters` if `filters` have changed', () => {
+ const filters = [{ property: 'city', label: 'City' }];
+ component.filters = filters;
+ component.previousFilters = [{ property: 'city', label: 'Previous City' }];
+
+ spyOn(component, 'onChangeFilters');
+ component.ngAfterViewInit();
+
+ expect(component.onChangeFilters).toHaveBeenCalledWith(filters);
+ expect(component.previousFilters).toEqual(filters);
+ });
+
+ it('should not call `onChangeFilters` if `filters` have not changed', () => {
+ const filters = [{ property: 'city', label: 'City' }];
+ component.filters = filters;
+ component.previousFilters = [...filters];
+
+ spyOn(component, 'onChangeFilters');
+
+ component.ngAfterViewInit();
+
+ expect(component.onChangeFilters).not.toHaveBeenCalled();
+ expect(component.previousFilters).toEqual(filters);
+ });
+ });
});
describe('Integration:', () => {
@@ -750,77 +842,48 @@ describe('PoPageDynamicSearchComponent:', () => {
expect(component.changeDisclaimers.emit).not.toHaveBeenCalled();
});
- it(`should add quickSearch and advanced filter in disclaimers if concat-filters is true and advanced filter is defined`, () => {
+ it(`should remove previous quickSearch disclaimer when adding a new quickSearch`, () => {
component.concatFilters = true;
-
- component.filters = [{ property: 'city', initValue: 'Ontario' }];
-
component.literals.quickSearchLabel = 'Search';
component.onAction('Chicago');
- const currentDisclaimers = [
- { label: 'City: Ontario', value: 'Ontario', property: 'city', hideClose: false },
- { property: 'search', label: `Search Chicago`, value: 'Chicago', hideClose: false }
- ];
-
- expect(component.disclaimerGroup.disclaimers).toEqual(currentDisclaimers);
- });
-
- it(`should add advanced filter and quickSearch updated in disclaimers if concat-filters is true and advanced filter is defined`, () => {
- component.concatFilters = true;
-
- component.filters = [{ property: 'city', initValue: 'Ontario' }];
-
- component.literals.quickSearchLabel = 'Search';
- component.onAction('Chicago');
+ expect(component.disclaimerGroup.disclaimers).toEqual([
+ {
+ property: 'search',
+ label: 'Search Chicago',
+ value: 'Chicago',
+ hideClose: false
+ }
+ ]);
component.onAction('Test');
- const currentDisclaimers = [
- { label: 'City: Ontario', value: 'Ontario', property: 'city', hideClose: false },
- { property: 'search', label: `Search Test`, value: 'Test', hideClose: false }
- ];
-
- expect(component.disclaimerGroup.disclaimers).toEqual(currentDisclaimers);
+ expect(component.disclaimerGroup.disclaimers).toEqual([
+ {
+ property: 'search',
+ label: 'Search Test',
+ value: 'Test',
+ hideClose: false
+ }
+ ]);
});
it(`should add advanced search and remove quickSearch in disclaimers if concat-filters is false`, () => {
component.concatFilters = false;
-
component.literals.quickSearchLabel = 'Search';
component.onAction('Chicago');
+
const disclaimersWithQuickFilter = [
{ property: 'search', label: `Search Chicago`, value: 'Chicago', hideClose: false }
];
-
expect(component.disclaimerGroup.disclaimers).toEqual(disclaimersWithQuickFilter);
- const disclaimersWithAdvancedSearch = [
- { label: 'City: Ontario', value: 'Ontario', property: 'city', hideClose: false }
- ];
-
component.filters = [{ property: 'city', initValue: 'Ontario' }];
-
- expect(component.disclaimerGroup.disclaimers).toEqual(disclaimersWithAdvancedSearch);
- });
-
- it(`should add advanced search and remove quickSearch in disclaimers if concat-filters is true`, () => {
- component.concatFilters = true;
-
- component.literals.quickSearchLabel = 'Search';
- component.onAction('Chicago');
- const disclaimersWithQuickFilter = [
- { property: 'search', label: `Search Chicago`, value: 'Chicago', hideClose: false }
- ];
-
- expect(component.disclaimerGroup.disclaimers).toEqual(disclaimersWithQuickFilter);
+ component.onAdvancedSearch({ filter: { city: 'Ontario' } });
const disclaimersWithAdvancedSearch = [
{ label: 'City: Ontario', value: 'Ontario', property: 'city', hideClose: false }
];
-
- component.filters = [{ property: 'city', initValue: 'Ontario' }];
-
expect(component.disclaimerGroup.disclaimers).toEqual(disclaimersWithAdvancedSearch);
});
});
diff --git a/projects/templates/src/lib/components/po-page-dynamic-search/po-page-dynamic-search.component.ts b/projects/templates/src/lib/components/po-page-dynamic-search/po-page-dynamic-search.component.ts
index 58a267189f..692f7feb78 100644
--- a/projects/templates/src/lib/components/po-page-dynamic-search/po-page-dynamic-search.component.ts
+++ b/projects/templates/src/lib/components/po-page-dynamic-search/po-page-dynamic-search.component.ts
@@ -1,4 +1,4 @@
-import { Component, ViewChild, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';
+import { Component, ViewChild, OnInit, OnDestroy, ChangeDetectorRef, AfterViewInit } from '@angular/core';
import { Observable, Subscription } from 'rxjs';
import {
@@ -43,7 +43,10 @@ type UrlOrPoCustomizationFunction = string | (() => PoPageDynamicSearchOptions);
selector: 'po-page-dynamic-search',
templateUrl: './po-page-dynamic-search.component.html'
})
-export class PoPageDynamicSearchComponent extends PoPageDynamicSearchBaseComponent implements OnInit, OnDestroy {
+export class PoPageDynamicSearchComponent
+ extends PoPageDynamicSearchBaseComponent
+ implements OnInit, OnDestroy, AfterViewInit
+{
@ViewChild(PoAdvancedFilterComponent, { static: true }) poAdvancedFilter: PoAdvancedFilterComponent;
@ViewChild(PoPageListComponent, { static: true }) poPageList: PoPageListComponent;
@@ -107,6 +110,14 @@ export class PoPageDynamicSearchComponent extends PoPageDynamicSearchBaseCompone
}
}
+ ngAfterViewInit(): void {
+ if (this.stringify(this.filters) !== this.stringify(this.previousFilters)) {
+ this.onChangeFilters(this.filters);
+
+ this.previousFilters = [...this.filters];
+ }
+ }
+
onChangeFilters(filters: Array) {
const filterObjectWithValue = filters
.filter(filter => filter.initValue)
@@ -152,7 +163,12 @@ export class PoPageDynamicSearchComponent extends PoPageDynamicSearchBaseCompone
onAdvancedSearch(filteredItems, isAdvancedSearch?) {
const { filter, optionsService } = filteredItems;
- this._disclaimerGroup.disclaimers = this.setDisclaimers(filter, optionsService);
+ const visibleFilters =
+ this.visibleFixedFilters === false
+ ? this.filters.filter(filter => !('fixed' in filter) || !filter.fixed)
+ : this.filters;
+
+ this._disclaimerGroup.disclaimers = this.setDisclaimers(filter, optionsService, visibleFilters);
this.setFilters(filter);
@@ -274,29 +290,51 @@ export class PoPageDynamicSearchComponent extends PoPageDynamicSearchBaseCompone
}
private onRemoveAllDisclaimers() {
- this.emitChangesDisclaimers([]);
+ const fixedFilters = this.filters.filter(
+ filter =>
+ filter.fixed === true &&
+ filter.hasOwnProperty('initValue') &&
+ filter.initValue !== undefined &&
+ filter.initValue !== null
+ );
+
+ const disclaimersToKeep = fixedFilters.map(filter => ({
+ property: filter.property,
+ value: filter.initValue,
+ label: `${filter.label}: ${filter.initValue}`,
+ hideClose: true
+ }));
+
+ this.emitChangesDisclaimers(disclaimersToKeep);
}
- private setDisclaimers(filters, optionsServiceObjects?: Array) {
+ private setDisclaimers(
+ filters,
+ optionsServiceObjects?: Array,
+ visibleFilters?: Array
+ ) {
const disclaimers = [];
const properties = Object.keys(filters);
+ const visibleProperties = visibleFilters ? visibleFilters.map(filter => filter.property) : properties;
properties.forEach(property => {
- const field = this.getFieldByProperty(this.filters, property);
- const label = field.label || capitalizeFirstLetter(field.property);
- const value = filters[property];
- const hideClose =
- this.hideCloseDisclaimers.some(hideCloseDisclaimer => hideCloseDisclaimer === property) || false;
-
- const valueDisplayedOnTheDisclaimerLabel = this.getFilterValueToDisclaimer(field, value, optionsServiceObjects);
-
- if (valueDisplayedOnTheDisclaimerLabel !== '') {
- disclaimers.push({
- label: `${label}: ${valueDisplayedOnTheDisclaimerLabel}`,
- property,
- value,
- hideClose
- });
+ if (visibleProperties.includes(property)) {
+ const field = this.getFieldByProperty(this.filters, property);
+ const label = field.label || capitalizeFirstLetter(field.property);
+ const value = filters[property];
+ const hideClose =
+ this.hideCloseDisclaimers.some(hideCloseDisclaimer => hideCloseDisclaimer === property) || false;
+
+ const valueDisplayedOnTheDisclaimerLabel = this.getFilterValueToDisclaimer(field, value, optionsServiceObjects);
+
+ if (valueDisplayedOnTheDisclaimerLabel !== '') {
+ disclaimers.push({
+ label: `${label}: ${valueDisplayedOnTheDisclaimerLabel}`,
+ property,
+ value,
+ hideClose
+ });
+ }
}
});
diff --git a/projects/templates/src/lib/components/po-page-dynamic-table/po-page-dynamic-table.component.html b/projects/templates/src/lib/components/po-page-dynamic-table/po-page-dynamic-table.component.html
index a264fb61c8..0fde4aa9ff 100644
--- a/projects/templates/src/lib/components/po-page-dynamic-table/po-page-dynamic-table.component.html
+++ b/projects/templates/src/lib/components/po-page-dynamic-table/po-page-dynamic-table.component.html
@@ -9,6 +9,7 @@
[p-hide-remove-all-disclaimer]="hideRemoveAllDisclaimer"
[p-quick-search-width]="quickSearchWidth"
[p-title]="title"
+ [p-visible-fixed-filters]="visibleFixedFilters"
(p-advanced-search)="onAdvancedSearch($event)"
(p-change-disclaimers)="onChangeDisclaimers($event)"
(p-quick-search)="onQuickSearch($event)"
diff --git a/projects/templates/src/lib/components/po-page-dynamic-table/po-page-dynamic-table.component.spec.ts b/projects/templates/src/lib/components/po-page-dynamic-table/po-page-dynamic-table.component.spec.ts
index 118015dce0..d9f6c3e60c 100644
--- a/projects/templates/src/lib/components/po-page-dynamic-table/po-page-dynamic-table.component.spec.ts
+++ b/projects/templates/src/lib/components/po-page-dynamic-table/po-page-dynamic-table.component.spec.ts
@@ -182,6 +182,18 @@ describe('PoPageDynamicTableComponent:', () => {
component.virtualScroll = true;
expect(component.virtualScroll).toBe(true);
});
+
+ it('p-visible-fixed-filters: should update property `p-visible-filter-disclaimers` to `false` when valid boolean value is given', () => {
+ component.visibleFixedFilters = false;
+
+ expect(component.visibleFixedFilters).toBe(false);
+ });
+
+ it('p-visible-fixed-filters: should update property `p-visible-filter-disclaimers` to `true` when valid boolean value is given', () => {
+ component.visibleFixedFilters = true;
+
+ expect(component.visibleFixedFilters).toBe(true);
+ });
});
describe('Methods:', () => {
diff --git a/projects/templates/src/lib/components/po-page-dynamic-table/po-page-dynamic-table.component.ts b/projects/templates/src/lib/components/po-page-dynamic-table/po-page-dynamic-table.component.ts
index a890c1531a..b4164bc0af 100644
--- a/projects/templates/src/lib/components/po-page-dynamic-table/po-page-dynamic-table.component.ts
+++ b/projects/templates/src/lib/components/po-page-dynamic-table/po-page-dynamic-table.component.ts
@@ -595,6 +595,26 @@ export class PoPageDynamicTableComponent extends PoPageDynamicListBaseComponent
return this._virtualScroll;
}
+ /**
+ * @optional
+ *
+ * @description
+ *
+ * Controla a visibilidade dos filtros fixos na página.
+ *
+ * - Quando `true` (default), todos os filtros, incluindo os fixos, são exibidos, permitindo que o usuário visualize os filtros aplicados.
+ * - Quando `false`, os filtros fixos são ocultados, não sendo exibidos na interface, mas ainda sendo aplicados como filtros nas requisições.
+ *
+ * Esta propriedade trabalha em conjunto com a propriedade `fixed` dos filtros individuais. Filtros marcados como `fixed: true` não serão exibidos na interface do filtro avançado quando `visibleFixedFilters` for `false`, mas continuarão a ser aplicados de forma transparente ao usuário. Dessa forma, permite-se maior flexibilidade no controle de quais filtros devem ser visíveis ao usuário ou devem ser aplicados permanentemente sem interferência.
+ *
+ * **Exemplo de uso:**
+ * ```html
+ *
+ *
+ * ```
+ */
+ @Input('p-visible-fixed-filters') visibleFixedFilters: boolean = true;
+
constructor(
private router: Router,
private activatedRoute: ActivatedRoute,