-
Notifications
You must be signed in to change notification settings - Fork 162
Public Row API Specification
Version | User | Date | Notes |
---|---|---|---|
0.1 | Hristo Anastasov | March 18, 2021 | Initial Draft |
0.2 | Hristo Anastasov | March 25, 2021 | API polishing, implementation without injecting row |
0.3 | Hristo Anastasov | April 13, 2021 | Details, Limitations |
0.4 | Hristo Anastasov | April 13, 2021 | Test plan |
Currently, grid APIs which return "row objects" are returning the actual row component from current state of the DOM. However this is far from useful as with the current implementation virtualization state is not taken into account (#6158) as well as exposing API which should not be usable by users of the grid.
As a solution, a new row-like interface should be exposed by the grids as the type returned from certain public API calls. This new interface will act as a façade for the core row API (while also taking the current virtualization state into account.
IgxGridRow
, IgxTreeGridRow
and IgxHierarchicalGridRow
are the new classes, which implement the new interface. These classes act as a façade for the corresponding row components: IgxGridRowComponent
, IgxTreeGridRowComponent
, IgxHierarchicalGridRowComponent
. (see below).
getRowByIndex
and getRowByKey
now should not depend on what is there in the virtualization container. This also includes the pinned rows, groupby rows and summary rows.
Internal functionalities and tests that depend on the rows DOM elements are changed to use gridAPI.get_row_by_index
or gridAPI.get_row_by_key
to work. Internal functionalities and tests that depend on the rows public API, continue use the public getRowByIndex
and getRowByKey
.
- Declare the public
RowType
interface, which defines the public properties/methods to be exposed in the public API.
export interface RowType {
index: number;
viewIndex?: number;
isGroupByRow?: boolean;
isSummaryRow?: boolean;
summaries?: Map<string, IgxSummaryResult[]>;
groupRow?: IGroupByRecord;
/** Deprecated, will be removed. key is the new property */
rowID?: any;
key?: any;
/** Deprecated, will be removed. data is the new property */
rowData?: any;
data?: any;
disabled?: boolean;
pinned?: boolean;
selected?: boolean;
expanded?: boolean;
deleted?: boolean;
inEditMode?: boolean;
children?: RowType[];
parent?: RowType;
hasChildren?: boolean;
treeRow?: ITreeGridRecord;
grid: GridType;
update?: (value: any) => void;
delete?: () => any;
pin?: () => void;
unpin?: () => void;
}
- Implement the new façade classes, which should implement the interface. This façade class takes the index of the row as parameter in the constructor, along with the corresponding grid component. Those are the only two needed to initialize the facade class instance - the index of the row and the grid.
IgxGridRow
, IgxTreeGridRow
and IgxHierarchicalGridRow
implement the same interface RowType
. The interface keeps most properties/methods optional, because igxGroupByRow
and IgxSummaryRow
also implement the same interface. This makes it possible for developers to always type the value returned from getRowByIndex
as RowType
regardless if the row at this index would happen to be a summary row or groupby row.
API calls happen over the grid api and grid services and nothing depends on the actual row component anymore.
export class IgxGridRow extends BaseRow{
public get pinned(): boolean {
return this.grid.isRecordPinned(this.data);
}
public set pinned(val: boolean) {
if (val) {
this.grid.pinRow(this.key);
} else {
this.grid.unpinRow(this.key);
}
}
constructor(protected grid: IgxGridBaseDirective & FlatGridType,
public index: number, protected _data?: any) {
super();
}
}
export class IgxTreeGridRow extends BaseRow {
public get treeRow(): ITreeGridRecord {
return this._tgrid.records.get(this.key);
}
constructor(protected grid: IgxGridBaseDirective & TreeGridType,
public index: number, protected _data?: any, private _treeRow?: ITreeGridRecord) {
super();
}
}
export class IgxHierarchicalGridRow extends BaseRow {
constructor(protected grid: IgxGridBaseDirective & HierarchicalGridType,
public index: number, protected _data?: any) {
super();
}
/**
* Returns true if row islands exist.
*/
public get hasChildren(): boolean {
return !!this.grid.childLayoutKeys.length;
}
}
- Cell instances continue to take the IgxRowDirective as
intRow
input for internal use.row
exposed by the cell component returns an instance of the corresponding row class.
/** @hidden @internal */
@Input()
public intRow: IgxRowDirective<IgxGridBaseDirective & GridType>;
/**
* Gets the row of the cell.
row: RowType = cell.row;
*/
@Input()
public get row(): RowType {
if (this.grid instanceof IgxTreeGridComponent) {
return new IgxTreeGridRow(this.grid, this.intRow.index, this.intRow.rowData, (this.intRow as IgxTreeGridRowComponent).treeRow);
}
if (this.grid instanceof IgxHierarchicalGridComponent) {
return new IgxHierarchicalGridRow(this.grid, this.intRow.index, this.intRow.rowData);
}
if (this.grid instanceof IgxGridComponent) {
return new IgxGridRow(this.grid, this.intRow.index, this.intRow.rowData);
}
}
- Make the public row API’s work with instances of the new classes. Those instances are created on demand in corresponding calls:
// grid.component.ts
// tree-grid.component.ts
// hierarchical-grid.component.ts
public getRowByIndex(index: number): RowType {
...
return this.createRow(index);
}
public getRowByKey(key: any): RowType {
...
return new IgxGridRow(this, index, rec);
}
// cell.component.ts
public get row(): RowType {
if (this.grid instanceof IgxTreeGridComponent) {
return new IgxTreeGridRow(this.grid, this.intRow.index, this.intRow.rowData, (this.intRow as IgxTreeGridRowComponent).treeRow);
} else if (this.grid instanceof IgxGridComponent) {
return new IgxGridRow(this.grid, this.intRow.index, this.intRow.rowData);
} else {
return new IgxHierarchicalGridRow(this.grid, this.intRow.index, this.intRow.rowData);
}
}
-
getRowByIndex
works per page (as it has always been), i.e. first row on any page of the grid has index 0 -
getRowByKey
will returnundefined
for a row that is on a different page, or is not visible if its parent (tree row or groupby row is collapsed) -
row
property emitted inIPinRowEventArgs
is now of typeRowType
-
dragData
property emitted inIRowDragStartEventArgs
,IRowDragEndEventArgs
is now of typeRowType
-
IRowDragStartEventArgs
,IRowDragEndEventArgs
now emitdragElement
property.
-
getRowByIndex
will now return an instance ofIgxSummaryRow
, instead ofundefined
, if there is a summary row at that index -
getRowByKey
will now returnundefined
, instead of a row instance, for a row, if its parent groupby row is collapsed. See test "should allows expanding/collapsing groups" -
rowData
is deprecated.data
is introduced -
rowID
is deprecated.key
is introduced -
toggle
method, exposed by the IgxHierarchicalRowComponent is not available. Useexpanded
property for all row types
There are currently many tests for all grids that use getRowByIndex
, getRowByKey
and cell.row
public APIs. Many of them verify correct rendering of the DOM elements, the rest of them verify the row public API usage.
- Those that verify the correct DOM rendering, need to be rewritten to use the
gridAPI.get_row_by_index
,gridAPI.get_row_by_key
andcell.intRow
. - Those that verify the usage of the public API, continue to use the
getRowByIndex
,getRowByKey
andcell.row
. Some of them cast the type returned asIgxRowComponent
, those casts need to be removed.
Test cases to be added:
Test | Should verify |
---|---|
use getRowByIndex to get a row that is out of the virtualized dom container |
row is returned |
use getRowByIndex to get a row that is first or last |
row is returned |
use getRowByIndex to get a row whose index exceeds last index of the current page |
undefined is returned |
use getRowByIndex(0) on different grid pages |
always returns the first row on the current page |
use getRowByKey to take a record, which is on another grid page |
returns undefined |
groupby in igx-grid, and use use getRowByKey to take a record, whose parent groupby row is collapsed |
returns undefined |
use use getRowByKey to take a record, whose parent tree row is collapsed |
returns undefined |
read row.hasChildren for igx-hierarchical-grid |
returns true if row has row islands |
read row.hasChildren for igx-tree-grid |
returns true if row has children |
read row.hasChildren for igx-grid |
always returns false |
groupBy the igx-grid and enable summaries for column. use getRowByIndex to get a row that happens to be a groupby row or summary row |
instance of the corresponding IgxGridRow , IgxSummaryRow or IgxGroupBy row to be returned |
Add top pinned records in grid. Use getRowByIndex(0) to get the top pinned record. |
instance of the pinned record to be returned |
Add bottom pinned records in grid. Use getRowByIndex(lastIndex) to get the bottom pinned record. |
instance of the pinned record to be returned |
Add pinned records in grid. Use the row API to select/delete the row, etc. | Both the data row and the pinned row should reflect the change |
Test the row API | Updates the corresponding state properly i.e. row.selected = true marks teh row as deleted |
Test the row.expanded API | Should work properly for IgxGridRow (when the grid has igxGridDetail template), IgxGroupByRow , IgxTreeGridRow and IgxHierarchicalGridRow
|