Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(grid): add new directives for re-templating header sorting indicators #10394

Merged
merged 12 commits into from
Nov 10, 2021
Merged
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ All notable changes for each version of this project will be documented in this
- Exposed new input `buttonText` which sets the text that is displayed inside the dropdown button in the toolbar.
- `IgxCombo`
- Added `groupSortingDirection` input, which allows you to set groups sorting order.
- `IgxGrid`, `IgxTreeGrid`, `IgxHierarchicalGrid`
- Added new directives for re-templating header sorting indicators - `IgxSortHeaderIconDirective`, `IgxSortAscendingHeaderIconDirective` and `IgxSortDescendingHeaderIconDirective`.

### General

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1603,11 +1603,15 @@
}

.sort-icon {
width: rem(15px);
height: rem(15px);
min-width: rem(15px); /* yeah IE, it really needs to be 15px wide... */
font-size: rem(15px);
position: relative;
display: flex;

igx-icon {
width: rem(15px);
height: rem(15px);
min-width: rem(15px); /* yeah IE, it really needs to be 15px wide... */
simeonoff marked this conversation as resolved.
Show resolved Hide resolved
font-size: rem(15px);
}

&::after {
content: attr(data-sortIndex);
Expand Down
79 changes: 49 additions & 30 deletions projects/igniteui-angular/src/lib/grids/grid-base.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,9 @@ import { CharSeparatedValueData } from '../services/csv/char-separated-value-dat
import { IgxColumnResizingService } from './resizing/resizing.service';
import { IFilteringStrategy } from '../data-operations/filtering-strategy';
import {
IgxRowExpandedIndicatorDirective, IgxRowCollapsedIndicatorDirective,
IgxHeaderExpandIndicatorDirective, IgxHeaderCollapseIndicatorDirective, IgxExcelStyleHeaderIconDirective
IgxRowExpandedIndicatorDirective, IgxRowCollapsedIndicatorDirective, IgxHeaderExpandIndicatorDirective,
IgxHeaderCollapseIndicatorDirective, IgxExcelStyleHeaderIconDirective, IgxSortAscendingHeaderIconDirective,
IgxSortDescendingHeaderIconDirective, IgxSortHeaderIconDirective
} from './grid/grid.directives';
import {
GridKeydownTargetType,
Expand Down Expand Up @@ -765,8 +766,8 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements
* <igx-grid #grid [data]="localData" (rowAdd)="rowAdd($event)" [height]="'305px'" [autoGenerate]="true"></igx-grid>
* ```
*/
@Output()
public rowAdd = new EventEmitter<IGridEditEventArgs>();
@Output()
public rowAdd = new EventEmitter<IGridEditEventArgs>();

/**
* Emitted after column is resized.
Expand Down Expand Up @@ -1252,6 +1253,24 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements
@ContentChild(IgxExcelStyleHeaderIconDirective, { read: TemplateRef })
public excelStyleHeaderIconTemplate: TemplateRef<any> = null;

/**
* The custom template, if any, that should be used when rendering a header sorting indicator when columns are sorted in asc order.
*/
@ContentChild(IgxSortAscendingHeaderIconDirective, { read: TemplateRef })
public sortAscendingHeaderIconTemplate: TemplateRef<any> = null;

/**
* The custom template, if any, that should be used when rendering a header sorting indicator when columns are sorted in desc order.
*/
@ContentChild(IgxSortDescendingHeaderIconDirective, { read: TemplateRef })
public sortDescendingHeaderIconTemplate: TemplateRef<any> = null;

/**
* The custom template, if any, that should be used when rendering a header sorting indicator when columns are not sorted.
*/
@ContentChild(IgxSortHeaderIconDirective, { read: TemplateRef })
public sortHeaderIconTemplate: TemplateRef<any> = null;

/**
* @hidden
* @internal
Expand Down Expand Up @@ -3442,26 +3461,26 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements
public setUpPaginator() {
if (this.paginator) {
this.paginator.pageChange.pipe(takeWhile(() => !!this.paginator), filter(() => !this._init))
.subscribe((page: number) => {
this.pageChange.emit(page);
});
.subscribe((page: number) => {
this.pageChange.emit(page);
});
this.paginator.pagingDone.pipe(takeWhile(() => !!this.paginator), filter(() => !this._init))
.subscribe((args: IPageEventArgs) => {
this.selectionService.clear(true);
this.pagingDone.emit({ previous: args.previous, current: args.current });
this.crudService.endEdit(false);
this.pipeTrigger++;
this.navigateTo(0);
this.notifyChanges();
});
.subscribe((args: IPageEventArgs) => {
this.selectionService.clear(true);
this.pagingDone.emit({ previous: args.previous, current: args.current });
this.crudService.endEdit(false);
this.pipeTrigger++;
this.navigateTo(0);
this.notifyChanges();
});
this.paginator.perPageChange.pipe(takeWhile(() => !!this.paginator), filter(() => !this._init))
.subscribe((perPage: number) => {
this.selectionService.clear(true);
this.perPageChange.emit(perPage);
this.paginator.page = 0;
this.crudService.endEdit(false);
this.notifyChanges();
});
.subscribe((perPage: number) => {
this.selectionService.clear(true);
this.perPageChange.emit(perPage);
this.paginator.page = 0;
this.crudService.endEdit(false);
this.notifyChanges();
});
} else {
this.markForCheck();
}
Expand Down Expand Up @@ -3932,7 +3951,7 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements
* ```
*/
public get columnsCollection(): IgxColumnComponent[] {
return this._rendered ? this._columns : [];
return this._rendered ? this._columns : [];
}

/**
Expand Down Expand Up @@ -4240,7 +4259,7 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements
* @param val
*/
// eslint-disable-next-line @typescript-eslint/member-ordering
@DeprecateMethod('Use the corresponding method exposed by the `igx-paginator`.')
@DeprecateMethod('Use the corresponding method exposed by the `igx-paginator`.')
public paginate(val: number): void {
this.paginator?.paginate(val);
}
Expand Down Expand Up @@ -5483,7 +5502,7 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements
const selectedColumns = this.gridAPI.grid.selectedColumns();
const columnData = this.getSelectedColumnsData(this.clipboardOptions.copyFormatters, this.clipboardOptions.copyHeaders);
let selectedData;
if (event.type === 'copy'){
if (event.type === 'copy') {
selectedData = this.getSelectedData(this.clipboardOptions.copyFormatters, this.clipboardOptions.copyHeaders);
};

Expand Down Expand Up @@ -5985,8 +6004,8 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements

protected subscribeToTransactions(): void {
this.transactionChange$.next();
this.transactions.onStateUpdate.pipe(takeUntil(merge(this.destroy$,this.transactionChange$)))
.subscribe(this.transactionStatusUpdate.bind(this));
this.transactions.onStateUpdate.pipe(takeUntil(merge(this.destroy$, this.transactionChange$)))
.subscribe(this.transactionStatusUpdate.bind(this));
}

protected transactionStatusUpdate(event: StateUpdateEvent) {
Expand Down Expand Up @@ -6746,10 +6765,10 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements
let selectionMap;
if (this.nativeElement.tagName.toLowerCase() === 'igx-hierarchical-grid' && selectionCollection.size > 0) {
selectionMap = isRemote ? Array.from(selectionCollection) :
Array.from(selectionCollection).filter((tuple) => tuple[0] < source.length);
}else {
Array.from(selectionCollection).filter((tuple) => tuple[0] < source.length);
} else {
selectionMap = isRemote ? Array.from(this.selectionService.selection) :
Array.from(this.selectionService.selection).filter((tuple) => tuple[0] < source.length);
Array.from(this.selectionService.selection).filter((tuple) => tuple[0] < source.length);
}

if (this.cellSelection === GridSelectionMode.single && activeEl) {
Expand Down
9 changes: 9 additions & 0 deletions projects/igniteui-angular/src/lib/grids/grid-common.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ import { IgxGridFilteringModule } from './filtering/base/filtering.module';
import { IgxRowDirective } from './row.directive';
import {
IgxExcelStyleHeaderIconDirective,
IgxSortAscendingHeaderIconDirective,
IgxSortDescendingHeaderIconDirective,
IgxSortHeaderIconDirective,
IgxGroupAreaDropDirective,
IgxHeaderCollapseIndicatorDirective,
IgxHeaderExpandIndicatorDirective,
Expand Down Expand Up @@ -58,6 +61,9 @@ import { IgxGroupByMetaPipe } from './grouping/group-by-area.directive';
IgxHeaderExpandIndicatorDirective,
IgxHeaderCollapseIndicatorDirective,
IgxExcelStyleHeaderIconDirective,
IgxSortAscendingHeaderIconDirective,
IgxSortDescendingHeaderIconDirective,
IgxSortHeaderIconDirective,
IgxGroupAreaDropDirective,
IgxGroupByMetaPipe
],
Expand Down Expand Up @@ -93,6 +99,9 @@ import { IgxGroupByMetaPipe } from './grouping/group-by-area.directive';
IgxHeaderExpandIndicatorDirective,
IgxHeaderCollapseIndicatorDirective,
IgxExcelStyleHeaderIconDirective,
IgxSortAscendingHeaderIconDirective,
IgxSortDescendingHeaderIconDirective,
IgxSortHeaderIconDirective,
IgxGroupAreaDropDirective,
IgxGroupByMetaPipe
],
Expand Down
27 changes: 27 additions & 0 deletions projects/igniteui-angular/src/lib/grids/grid/grid.directives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,33 @@ export class IgxHeaderCollapseIndicatorDirective {
export class IgxExcelStyleHeaderIconDirective {
}

/**
* @hidden
*/
@Directive({
selector: '[igxSortHeaderIcon]'
})
export class IgxSortHeaderIconDirective {
}

/**
* @hidden
*/
@Directive({
selector: '[igxSortAscendingHeaderIcon]'
})
export class IgxSortAscendingHeaderIconDirective {
}

/**
* @hidden
*/
@Directive({
selector: '[igxSortDescendingHeaderIcon]'
})
export class IgxSortDescendingHeaderIconDirective {
}

/**
* @hidden
*/
Expand Down
21 changes: 21 additions & 0 deletions projects/igniteui-angular/src/lib/grids/grid/grid.sorting.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -549,5 +549,26 @@ describe('IgxGrid - Grid Sorting #grid', () => {
expect(grid.sorting.emit).toHaveBeenCalledTimes(2);
expect(grid.sortingDone.emit).toHaveBeenCalledTimes(2);
}));

it('Should allow setting custom templates for header sorting none/ascending/descending icons.', () => {
fixture = TestBed.createComponent(SortByParityComponent);
fixture.detectChanges();
grid = fixture.componentInstance.grid;
const fieldName = 'Name';
const header = GridFunctions.getColumnHeader(fieldName, fixture, grid);
let icon = GridFunctions.getHeaderSortIcon(header);

expect(icon.nativeElement.textContent.toLowerCase().trim()).toBe('unfold_more');

grid.sort({ fieldName, dir: SortingDirection.Asc, ignoreCase: false });
fixture.detectChanges();
icon = GridFunctions.getHeaderSortIcon(header);
expect(icon.nativeElement.textContent.toLowerCase().trim()).toBe('expand_less');

grid.sort({ fieldName, dir: SortingDirection.Desc, ignoreCase: false });
fixture.detectChanges();
icon = GridFunctions.getHeaderSortIcon(header);
expect(icon.nativeElement.textContent.toLowerCase().trim()).toBe('expand_more');
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,28 @@
<igx-icon>more_vert</igx-icon>
</ng-template>

<ng-template #defaultSortHeaderIconTemplate>
<igx-icon>{{ sortDirection < 2 ? 'arrow_upward' : 'arrow_downward' }}</igx-icon>
</ng-template>

<span class="igx-grid-th__title">
<ng-container *ngTemplateOutlet="column.headerTemplate ? column.headerTemplate : defaultColumn; context: { $implicit: column, column: column}">
<ng-container
*ngTemplateOutlet="column.headerTemplate ? column.headerTemplate : defaultColumn; context: { $implicit: column, column: column}">
</ng-container>
</span>
<ng-container *ngIf="!column.columnGroup">
<div class="igx-grid-th__icons">
<ng-container *ngIf="column.sortable">
<igx-icon class="sort-icon"
[attr.draggable]="false"
[attr.data-sortIndex]="column.field | sortingIndex:grid.sortingExpressions"
(click)="onSortingIconClick($event)">
{{ sortDirection < 2 ? 'arrow_upward' : 'arrow_downward' }}
</igx-icon>
<div class="sort-icon" [attr.data-sortIndex]="column.field | sortingIndex:grid.sortingExpressions"
[attr.draggable]="false" (click)="onSortingIconClick($event)" (pointerdown)="$event.stopPropagation()">
<ng-container *ngTemplateOutlet="sortIconTemplate; context: { $implicit: this }"></ng-container>
</div>
</ng-container>
<ng-container *ngIf="grid.allowFiltering && column.filterable && grid.filterMode === 'excelStyleFilter'">
<div [ngClass]="filterIconClassName" (click)="onFilteringIconClick($event)" (pointerdown)="$event.stopPropagation()">
<div [ngClass]="filterIconClassName" (click)="onFilteringIconClick($event)"
(pointerdown)="$event.stopPropagation()">
<ng-container *ngTemplateOutlet="esfIconTemplate; context: { $implicit: this }"></ng-container>
</div>
</ng-container>
</div>
</ng-container>
</ng-container>
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ export class IgxGridHeaderComponent implements DoCheck, OnDestroy {
@ViewChild('defaultESFHeaderIconTemplate', { read: TemplateRef, static: true })
protected defaultESFHeaderIconTemplate: TemplateRef<any>;

/**
* @hidden
*/
@ViewChild('defaultSortHeaderIconTemplate', { read: TemplateRef, static: true })
protected defaultSortHeaderIconTemplate;

/**
* Returns the `aria-selected` of the header.
*/
Expand Down Expand Up @@ -131,6 +137,21 @@ export class IgxGridHeaderComponent implements DoCheck, OnDestroy {
return this.grid.excelStyleHeaderIconTemplate || this.defaultESFHeaderIconTemplate;
}

/**
* @hidden
*/
public get sortIconTemplate() {
if (this.sortDirection === SortingDirection.None && this.grid.sortHeaderIconTemplate) {
return this.grid.sortHeaderIconTemplate;
} else if (this.sortDirection === SortingDirection.Asc && this.grid.sortAscendingHeaderIconTemplate) {
return this.grid.sortAscendingHeaderIconTemplate;
} else if (this.sortDirection === SortingDirection.Desc && this.grid.sortDescendingHeaderIconTemplate) {
return this.grid.sortDescendingHeaderIconTemplate;
} else {
return this.defaultSortHeaderIconTemplate;
}
}

public get sorted() {
return this.sortDirection !== SortingDirection.None;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,9 @@ export class IgxHierarchicalGridComponent extends IgxHierarchicalGridBaseDirecti
this.headerCollapseIndicatorTemplate = this.rootGrid.headerCollapseIndicatorTemplate;
this.headerExpandIndicatorTemplate = this.rootGrid.headerExpandIndicatorTemplate;
this.excelStyleHeaderIconTemplate = this.rootGrid.excelStyleHeaderIconTemplate;
this.sortAscendingHeaderIconTemplate = this.rootGrid.sortAscendingHeaderIconTemplate;
this.sortDescendingHeaderIconTemplate = this.rootGrid.sortDescendingHeaderIconTemplate;
this.sortHeaderIconTemplate = this.rootGrid.sortHeaderIconTemplate;
this.hasChildrenKey = this.parentIsland ?
this.parentIsland.hasChildrenKey || this.rootGrid.hasChildrenKey :
this.rootGrid.hasChildrenKey;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1819,7 +1819,7 @@ export class GridFunctions {

public static getColumnGroupHeaderCell(columnField: string, fix: ComponentFixture<any>) {
const headerTitle = fix.debugElement.queryAll(By.css(GROUP_HEADER_CLASS))
.find(header => header.nativeElement.title === columnField);
.find(header => header.nativeElement.title === columnField);
return headerTitle.parent;
}

Expand Down Expand Up @@ -1867,7 +1867,7 @@ export class GridFunctions {
}

public static getHeaderSortIcon(header: DebugElement): DebugElement {
return header.query(By.css(SORT_ICON_CLASS));
return header.query(By.css(SORT_ICON_CLASS))?.query(By.css('igx-icon'));
}

public static getHeaderFilterIcon(header: DebugElement): DebugElement {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
} from './grid-base-components.spec';
import { IGridSelection } from './grid-interfaces.spec';
import { SampleTestData, DataParent } from './sample-test-data.spec';
import { ColumnDefinitions, GridTemplateStrings, EventSubscriptions } from './template-strings.spec';
import { ColumnDefinitions, GridTemplateStrings, EventSubscriptions, TemplateDefinitions } from './template-strings.spec';
import { IgxColumnComponent } from '../grids/columns/column.component';
import { IgxFilteringOperand, IgxNumberFilteringOperand } from '../data-operations/filtering-condition';
import { ExpressionUI } from '../grids/filtering/grid-filtering.service';
Expand Down Expand Up @@ -2276,7 +2276,10 @@ export class NoColumnWidthGridComponent extends BasicGridComponent {
template: GridTemplateStrings.declareGrid(
'',
'',
ColumnDefinitions.idFirstLastNameSortable)
ColumnDefinitions.idFirstLastNameSortable,
'',
'',
TemplateDefinitions.sortIconTemplates)
})
export class SortByParityComponent extends GridDeclaredColumnsComponent implements ISortingStrategy {
public sort(data: any[], fieldName: string, dir: SortingDirection) {
Expand Down
Loading