Skip to content

Commit 5dad161

Browse files
authored
Merge pull request #17083 from IgniteUI/copilot/clarify-percent-filter-ui
feat(grids/filtering): Add percent representation hint to filter inputs for percent columns
2 parents 85a1a12 + 9353257 commit 5dad161

File tree

10 files changed

+284
-176
lines changed

10 files changed

+284
-176
lines changed

package-lock.json

Lines changed: 166 additions & 162 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

projects/igniteui-angular/core/src/core/styles/components/grid/_grid-theme.scss

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@
306306
%filtering-row-input-overrides {
307307
igx-input-group {
308308
width: 100%;
309-
max-width: rem(200px);
309+
max-width: rem(240px);
310310
min-width: rem(140px);
311311

312312
@if $variant != 'fluent' {
@@ -2482,6 +2482,16 @@
24822482
margin: rem(4px);
24832483
}
24842484
}
2485+
2486+
.igx-grid__filtering-row-percent-hint {
2487+
display: inline-block;
2488+
max-width: rem(56px);
2489+
overflow: hidden;
2490+
text-overflow: ellipsis;
2491+
white-space: nowrap;
2492+
vertical-align: middle;
2493+
flex-shrink: 1;
2494+
}
24852495
}
24862496

24872497
%igx-grid__filtering-dropdown-items {

projects/igniteui-angular/grids/core/src/filtering/base/grid-filtering-row.component.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@
3838
(keyup)="onInputKeyUp()"/>
3939
@if (value || value === 0) {
4040
<igx-suffix>
41+
@if (column.dataType === 'percent') {
42+
<span class="igx-grid__filtering-row-percent-hint">{{ value | percent:column.pipeArgs.digitsInfo:filteringService.grid.locale }}</span>
43+
}
4144
<igx-icon
4245
(keydown)="onCommitKeyDown($event)"
4346
(click)="onCommitClick()"

projects/igniteui-angular/grids/core/src/filtering/base/grid-filtering-row.component.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,22 @@ import { IBaseChipEventArgs, IgxChipComponent, IgxChipsAreaComponent } from 'ign
2626
import { IgxIconComponent } from 'igniteui-angular/icon';
2727
import { IgxInputDirective, IgxInputGroupComponent, IgxPrefixDirective, IgxSuffixDirective } from 'igniteui-angular/input-group';
2828
import { IgxDatePickerComponent } from 'igniteui-angular/date-picker';
29-
import { AbsoluteScrollStrategy, ColumnType, ConnectedPositioningStrategy, DataUtil, FilteringLogic, GridColumnDataType, HorizontalAlignment, IFilteringExpression, IFilteringOperation, IgxPickerClearComponent, IgxPickerToggleComponent, isEqual, OverlaySettings, PlatformUtil, ɵSize, VerticalAlignment } from 'igniteui-angular/core';
29+
import { AbsoluteScrollStrategy, ColumnType, ConnectedPositioningStrategy, DataUtil, FilteringLogic, GridColumnDataType, HorizontalAlignment, IFilteringExpression, IFilteringOperation, IgxPercentFormatterPipe, IgxPickerClearComponent, IgxPickerToggleComponent, isEqual, OverlaySettings, PlatformUtil, ɵSize, VerticalAlignment } from 'igniteui-angular/core';
3030
import { IgxTimePickerComponent } from 'igniteui-angular/time-picker';
3131
import { IgxButtonDirective, IgxDateTimeEditorDirective, IgxIconButtonDirective, IgxRippleDirective } from 'igniteui-angular/directives';
3232

33+
/**
34+
* Default debounce time (ms) for filtering row inputs.
35+
* @hidden
36+
*/
37+
export const INPUT_DEBOUNCE_TIME_DEFAULT = 350;
38+
3339
/**
3440
* Injection token for setting the debounce time used in filtering row inputs.
3541
* @hidden
3642
*/
3743
export const INPUT_DEBOUNCE_TIME = /*@__PURE__*/new InjectionToken<number>('INPUT_DEBOUNCE_TIME', {
38-
factory: () => 350
44+
factory: () => INPUT_DEBOUNCE_TIME_DEFAULT
3945
});
4046

4147
/**
@@ -65,7 +71,8 @@ export const INPUT_DEBOUNCE_TIME = /*@__PURE__*/new InjectionToken<number>('INPU
6571
IgxButtonDirective,
6672
NgClass,
6773
IgxRippleDirective,
68-
IgxIconButtonDirective
74+
IgxIconButtonDirective,
75+
IgxPercentFormatterPipe
6976
]
7077
})
7178
export class IgxGridFilteringRowComponent implements OnInit, AfterViewInit, OnDestroy {
@@ -280,6 +287,7 @@ export class IgxGridFilteringRowComponent implements OnInit, AfterViewInit, OnDe
280287
return 'text';
281288
case GridColumnDataType.Number:
282289
case GridColumnDataType.Currency:
290+
case GridColumnDataType.Percent:
283291
return 'number';
284292
}
285293
}

projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-default-expression.component.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@
3333
[(ngModel)]="expressionUI.expression.searchVal"
3434
(blur)="updateSearchValueOnBlur($event)"
3535
/>
36+
@if (column.dataType === 'percent' && (expressionUI.expression.searchVal || expressionUI.expression.searchVal === 0)) {
37+
<igx-suffix>
38+
<span class="igx-grid__filtering-row-percent-hint">{{ expressionUI.expression.searchVal | percent:column.pipeArgs.digitsInfo:grid.locale }}</span>
39+
</igx-suffix>
40+
}
3641
</igx-input-group>
3742

3843
@if (!isSingle) {

projects/igniteui-angular/grids/core/src/filtering/excel-style/excel-style-default-expression.component.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { Component, AfterViewInit, Input, Output, EventEmitter, ChangeDetectorRef, ViewChild, inject } from '@angular/core';
22
import { FormsModule } from '@angular/forms';
33
import { ExpressionUI } from './common';
4-
import { AbsoluteScrollStrategy, ColumnType, ConnectedPositioningStrategy, DataUtil, FilteringLogic, GridColumnDataType, IBaseEventArgs, IFilteringOperation, IgxOverlayOutletDirective, OverlaySettings, PlatformUtil } from 'igniteui-angular/core';
4+
import { AbsoluteScrollStrategy, ColumnType, ConnectedPositioningStrategy, DataUtil, FilteringLogic, GridColumnDataType, IBaseEventArgs, IFilteringOperation, IgxOverlayOutletDirective, IgxPercentFormatterPipe, OverlaySettings, PlatformUtil } from 'igniteui-angular/core';
55
import { IgxSelectComponent, IgxSelectItemComponent } from 'igniteui-angular/select';
6-
import { IgxInputDirective, IgxInputGroupComponent, IgxPrefixDirective } from 'igniteui-angular/input-group';
6+
import { IgxInputDirective, IgxInputGroupComponent, IgxPrefixDirective, IgxSuffixDirective } from 'igniteui-angular/input-group';
77
import { IgxIconComponent } from 'igniteui-angular/icon';
88
import { IgxButtonDirective, IgxIconButtonDirective } from 'igniteui-angular/directives';
99
import { IgxButtonGroupComponent } from 'igniteui-angular/button-group';
@@ -22,7 +22,7 @@ export interface ILogicOperatorChangedArgs extends IBaseEventArgs {
2222
@Component({
2323
selector: 'igx-excel-style-default-expression',
2424
templateUrl: './excel-style-default-expression.component.html',
25-
imports: [FormsModule, IgxSelectComponent, IgxPrefixDirective, IgxIconComponent, IgxSelectItemComponent, IgxInputGroupComponent, IgxInputDirective, IgxButtonDirective, IgxButtonGroupComponent, IgxOverlayOutletDirective, IgxIconButtonDirective]
25+
imports: [FormsModule, IgxSelectComponent, IgxPrefixDirective, IgxIconComponent, IgxSelectItemComponent, IgxInputGroupComponent, IgxInputDirective, IgxSuffixDirective, IgxButtonDirective, IgxButtonGroupComponent, IgxOverlayOutletDirective, IgxIconButtonDirective, IgxPercentFormatterPipe]
2626
})
2727
export class IgxExcelStyleDefaultExpressionComponent implements AfterViewInit {
2828
public cdr = inject(ChangeDetectorRef);

projects/igniteui-angular/grids/grid/src/column.spec.ts

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import {
2020
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
2121
import { UIInteractions, wait } from '../../../test-utils/ui-interactions.spec';
2222
import { GridFunctions, GridSummaryFunctions } from '../../../test-utils/grid-functions.spec';
23-
import { IgxCellFooterTemplateDirective, IgxCellHeaderTemplateDirective, IgxCellTemplateDirective, IgxColumnComponent, IgxSummaryTemplateDirective } from 'igniteui-angular/grids/core';
23+
import { IgxCellFooterTemplateDirective, IgxCellHeaderTemplateDirective, IgxCellTemplateDirective, IgxColumnComponent, INPUT_DEBOUNCE_TIME_DEFAULT, IgxSummaryTemplateDirective } from 'igniteui-angular/grids/core';
2424
import { IgxGridRowComponent } from './grid-row.component';
2525
import { GridColumnDataType, IgxStringFilteringOperand, SortingDirection } from 'igniteui-angular/core';
2626
import { IgxButtonDirective, IgxDateTimeEditorDirective } from 'igniteui-angular/directives';
@@ -838,6 +838,77 @@ describe('IgxGrid - Column properties #grid', () => {
838838
expect((checkBoxes[3].querySelector('.igx-checkbox__label') as HTMLElement).innerText).toEqual('002.700%');
839839
}));
840840

841+
it('should show percent suffix in filter row when filtering a percent column', fakeAsync(() => {
842+
const fix = TestBed.createComponent(IgxGridPercentColumnComponent);
843+
fix.detectChanges();
844+
845+
const grid = fix.componentInstance.grid;
846+
const discountColumn = grid.getColumnByName('Discount');
847+
grid.allowFiltering = true;
848+
fix.detectChanges();
849+
850+
GridFunctions.clickFilterCellChip(fix, discountColumn.field);
851+
tick(100);
852+
fix.detectChanges();
853+
854+
const filterUIRow = fix.debugElement.query(By.css('igx-grid-filtering-row'));
855+
const input = filterUIRow.query(By.directive(IgxInputDirective));
856+
857+
// Suffix should not be visible before entering a value
858+
let percentLabel = filterUIRow.query(By.css('.igx-grid__filtering-row-percent-hint'));
859+
expect(percentLabel).toBeNull();
860+
861+
// Enter a value to trigger the suffix; wait for the filter row input debounce
862+
GridFunctions.typeValueInFilterRowInput(0.03, fix, input);
863+
tick(INPUT_DEBOUNCE_TIME_DEFAULT);
864+
fix.detectChanges();
865+
866+
percentLabel = filterUIRow.query(By.css('.igx-grid__filtering-row-percent-hint'));
867+
expect(percentLabel).not.toBeNull();
868+
expect(percentLabel.nativeElement.textContent.trim()).toEqual('3%');
869+
}));
870+
871+
it('should show percent suffix in ESF custom dialog when filtering a percent column', fakeAsync(() => {
872+
const fix = TestBed.createComponent(IgxGridPercentColumnComponent);
873+
tick();
874+
fix.detectChanges();
875+
876+
const grid = fix.componentInstance.grid;
877+
const discountColumn = grid.getColumnByName('Discount');
878+
grid.allowFiltering = true;
879+
grid.filterMode = 'excelStyleFilter';
880+
fix.detectChanges();
881+
882+
GridFunctions.clickExcelFilterIcon(fix, discountColumn.field);
883+
tick(100);
884+
fix.detectChanges();
885+
886+
GridFunctions.clickExcelFilterCascadeButton(fix);
887+
tick(100);
888+
fix.detectChanges();
889+
890+
// Open custom filter dialog by selecting first operator (Equals)
891+
GridFunctions.clickOperatorFromCascadeMenu(fix, 0);
892+
tick(200);
893+
fix.detectChanges();
894+
895+
const exprComponents = GridFunctions.getExcelCustomFilteringDefaultExpressions(fix);
896+
expect(exprComponents.length).toBeGreaterThan(0);
897+
898+
// Percent label should not be visible before entering a value
899+
let percentLabel = exprComponents[0].querySelector('.igx-grid__filtering-row-percent-hint');
900+
expect(percentLabel).toBeNull();
901+
902+
// Enter a value to trigger the suffix
903+
GridFunctions.setInputValueESF(fix, 0, 0.05);
904+
tick(100);
905+
fix.detectChanges();
906+
907+
percentLabel = exprComponents[0].querySelector('.igx-grid__filtering-row-percent-hint');
908+
expect(percentLabel).not.toBeNull();
909+
expect(percentLabel.textContent.trim()).toEqual('5%');
910+
}));
911+
841912
});
842913

843914
describe('Date, DateTime and Time column tests', () => {

projects/igniteui-angular/grids/grid/src/grid-filtering-ui.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1977,7 +1977,7 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => {
19771977
}));
19781978

19791979
it('should scroll correct chip in view when one is deleted', async () => {
1980-
grid.width = '800px';
1980+
grid.width = '840px';
19811981
fix.detectChanges();
19821982
await wait(DEBOUNCE_TIME);
19831983

src/app/grid-filtering/grid-filtering.sample.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Component, ViewChild, OnInit, HostBinding } from '@angular/core';
22
import { FormsModule } from '@angular/forms';
3-
import { FilterMode, FilteringExpressionsTree, FilteringLogic, FormattedValuesFilteringStrategy, GridSelectionMode, IChangeCheckboxEventArgs, IGX_GRID_DIRECTIVES, IgxButtonGroupComponent, IgxCheckboxComponent, IgxGridComponent, IgxIconComponent, IgxStringFilteringOperand } from 'igniteui-angular';
3+
import { FilterMode, FilteringExpressionsTree, FilteringLogic, FormattedValuesFilteringStrategy, GridSelectionMode, IChangeCheckboxEventArgs, IGX_GRID_DIRECTIVES, IgxButtonDirective, IgxButtonGroupComponent, IgxCheckboxComponent, IgxGridComponent, IgxIconComponent, IgxStringFilteringOperand } from 'igniteui-angular';
44
import { SAMPLE_DATA } from '../shared/sample-data';
55

66

@@ -9,7 +9,14 @@ import { SAMPLE_DATA } from '../shared/sample-data';
99
selector: 'app-grid-filtering-sample',
1010
styleUrls: ['grid-filtering.sample.scss'],
1111
templateUrl: 'grid-filtering.sample.html',
12-
imports: [FormsModule, IGX_GRID_DIRECTIVES, IgxCheckboxComponent, IgxButtonGroupComponent, IgxIconComponent]
12+
imports: [
13+
FormsModule,
14+
IGX_GRID_DIRECTIVES,
15+
IgxCheckboxComponent,
16+
IgxButtonGroupComponent,
17+
IgxIconComponent,
18+
IgxButtonDirective
19+
]
1320
})
1421
export class GridFilteringComponent implements OnInit {
1522

src/app/grid-percentage-columns/grid-percantge-widths.sample.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<div class="wrapper">
22
<div class="sample-content">
33
<div class="sample-column">
4-
<igx-grid [data]="data" [locale]="locale" [allowFiltering]="true" [moving]="true" [filterMode]="'excelStyleFilter'" width="420px" height="600px">
4+
<igx-grid [data]="data" [locale]="locale" [allowFiltering]="true" [moving]="true" [filterMode]="'excelStyleFilter'" width="100%" height="600px">
55
<igx-column field="ProductName" [pinned]="false" header="Product Name" width="20%" [dataType]="'string'" [sortable]="true" [hasSummary]="false" [editable]="true" [filterable]="true" >
66
</igx-column>
77
<igx-column field="UnitsInStock" [pinned]="false" header="Units In Stock" width="20%" dataType="currency" [pipeArgs]="pipeArgs" [sortable]="true" [hasSummary]="true" [editable]="true" [filterable]="true" >
@@ -11,10 +11,10 @@
1111
{{val | date:'dd/MM/yyyy'}}
1212
</ng-template>
1313
</igx-column>
14-
<igx-column field="Discontinued" header="Discontinued" width="10%" [dataType]="'boolean'" minWidth="20px"
14+
<igx-column field="Discontinued" header="Discontinued" width="10%" [dataType]="'boolean'" minWidth="20px"
1515
[sortable]="false" [hasSummary]="false" [editable]="true" [filterable]="false">
1616
</igx-column>
17-
<igx-column field="ReorderLevel" header="Reorder Level" dataType="percent" [pipeArgs]="pipeArgs" [hasSummary]="true" width="10%" [sortable]="false" [editable]="true" >
17+
<igx-column field="ReorderLevel" header="Reorder Level" dataType="percent" [pipeArgs]="pipeArgs" [hasSummary]="true" width="10%" [sortable]="false" [editable]="true" >
1818
</igx-column>
1919
<igx-column field="SupplierID" header="SupplierID" width="10%" [sortable]="false" [editable]="true">
2020
</igx-column>

0 commit comments

Comments
 (0)