Filters, Editors, AsyncPostRender with Angular Components
Grid with usage of Angular Components as Editor & AsyncPostRender (similar to Formatter).
Support of Angular Component as Custom Editor (click on any "Assignee" name cell)
That column uses ng-select as a custom editor as an Angular Component
-
Increased Grid Options "rowHeight" to 45 so that the "ng-select" fits in the cell. Ideally it would be better to override the ng-select css styling to change it's max height
+
Increased Grid Options "rowHeight" & "headerRowHeight" to 45 so that the "ng-select" fits in the cell. Ideally it would be better to override the ng-select css styling to change it's max height
+
Support of Angular Component as Custom Filter ("Assignee" columns), which also uses "ng-select"
The 2nd "Assignee" column (showing in bold text) uses "asyncPostRender" with an Angular Component
+
+
Why can't we use Angular Component as Customer Formatter and why do I see a slight delay in loading the data?
+
It's totally normal since SlickGrid Formatters only accept strings (synchronously),
+ so we cannot use that (Angular requires at least 1 full cycle to render the element), so we are left with SlickGrid "asyncPostRender" and
+ it works but as the name suggest it's async users might see noticeable delay in loading the data
+
+
`;
@@ -51,6 +64,7 @@ export class GridAngularComponent implements OnInit {
updatedObject: any;
selectedLanguage = 'en';
assignees = [
+ { id: '', name: '' },
{ id: '1', name: 'John' },
{ id: '2', name: 'Pierre' },
{ id: '3', name: 'Paul' },
@@ -91,10 +105,18 @@ export class GridAngularComponent implements OnInit {
minWidth: 100,
filterable: true,
sortable: true,
- type: FieldType.string,
+ filter: {
+ model: new CustomAngularComponentFilter(), // create a new instance to make each Filter independent from each other
+ collection: this.assignees,
+ params: {
+ component: FilterNgSelectComponent,
+ }
+ },
+ queryFieldFilter: 'assignee.id', // for a complex object it's important to tell the Filter which field to query and our CustomAngularComponentFilter returns the "id" property
+ queryFieldSorter: 'assignee.name',
formatter: Formatters.complexObject,
params: {
- complexField: 'assignee.name',
+ complexFieldLabel: 'assignee.name',
},
exportWithFormatter: true,
editor: {
@@ -115,7 +137,15 @@ export class GridAngularComponent implements OnInit {
minWidth: 100,
filterable: true,
sortable: true,
- type: FieldType.string,
+ filter: {
+ model: new CustomAngularComponentFilter(), // create a new instance to make each Filter independent from each other
+ collection: this.assignees,
+ params: {
+ component: FilterNgSelectComponent,
+ }
+ },
+ queryFieldFilter: 'assignee.id', // for a complex object it's important to tell the Filter which field to query and our CustomAngularComponentFilter returns the "id" property
+ queryFieldSorter: 'assignee.name',
// loading formatter, text to display while Post Render gets processed
formatter: () => '...',
@@ -127,8 +157,9 @@ export class GridAngularComponent implements OnInit {
params: {
component: CustomTitleFormatterComponent,
angularUtilService: this.angularUtilService,
+ complexFieldLabel: 'assignee.name' // for the exportCustomFormatter
},
- exportWithFormatter: true,
+ exportCustomFormatter: Formatters.complexObject,
}, {
id: 'complete',
name: '% Complete',
@@ -148,21 +179,15 @@ export class GridAngularComponent implements OnInit {
label: 'label',
labelSuffix: 'symbol'
},
-
- // collection: Array.from(Array(101).keys()).map(k => ({ value: k, label: k, labelSuffix: '%' })),
- collectionSortBy: {
- property: 'label',
- sortDesc: true
- },
- collectionFilterBy: {
- property: 'value',
- value: 0,
- operator: OperatorType.notEqual
- },
elementOptions: {
maxHeight: 400
}
},
+ filter: {
+ model: Filters.slider,
+ operator: '>=',
+ params: { hideSliderNumber: false }
+ },
params: {
formatters: [Formatters.collectionEditor, Formatters.percentCompleteBar],
}
@@ -205,6 +230,7 @@ export class GridAngularComponent implements OnInit {
containerId: 'demo-container',
sidePadding: 15
},
+ headerRowHeight: 45,
rowHeight: 45, // increase row height so that the ng-select fits in the cell
editable: true,
enableCellNavigation: true,
@@ -238,7 +264,7 @@ export class GridAngularComponent implements OnInit {
tempDataset.push({
id: i,
title: 'Task ' + i,
- assignee: i % 3 ? this.assignees[2] : i % 2 ? this.assignees[1] : this.assignees[0],
+ assignee: i % 3 ? this.assignees[3] : i % 2 ? this.assignees[2] : this.assignees[1],
duration: Math.round(Math.random() * 100) + '',
percentComplete: randomPercent,
percentCompleteNumber: randomPercent,
diff --git a/src/app/examples/grid-editor.component.html b/src/app/examples/grid-editor.component.html
index dd8466ebd..4af2b6734 100644
--- a/src/app/examples/grid-editor.component.html
+++ b/src/app/examples/grid-editor.component.html
@@ -3,7 +3,7 @@
{{title}}
- autoEdit setting
+ autoEdit setting:
ON (single-click)
diff --git a/src/app/examples/grid-editor.component.ts b/src/app/examples/grid-editor.component.ts
index 5d6f4ac42..07e23c136 100644
--- a/src/app/examples/grid-editor.component.ts
+++ b/src/app/examples/grid-editor.component.ts
@@ -240,6 +240,7 @@ export class GridEditorComponent implements OnInit {
filterable: true,
filter: { model: Filters.compoundDate },
formatter: Formatters.dateIso,
+ exportWithFormatter: true,
sortable: true,
type: FieldType.date,
editor: {
@@ -254,6 +255,7 @@ export class GridEditorComponent implements OnInit {
sortable: true,
filter: { model: Filters.compoundDate },
formatter: Formatters.dateIso,
+ exportWithFormatter: true,
type: FieldType.date,
editor: {
model: Editors.date
@@ -309,6 +311,7 @@ export class GridEditorComponent implements OnInit {
}, {
id: 'countryOfOrigin', name: 'Country of Origin', field: 'countryOfOrigin',
formatter: Formatters.complexObject,
+ exportWithFormatter: true,
dataKey: 'code',
labelKey: 'name',
type: FieldType.object,
diff --git a/src/app/modules/angular-slickgrid/components/angular-slickgrid.component.ts b/src/app/modules/angular-slickgrid/components/angular-slickgrid.component.ts
index eb93ed1ca..6f53be7db 100644
--- a/src/app/modules/angular-slickgrid/components/angular-slickgrid.component.ts
+++ b/src/app/modules/angular-slickgrid/components/angular-slickgrid.component.ts
@@ -478,7 +478,7 @@ export class AngularSlickgridComponent implements AfterViewInit, OnDestroy, OnIn
// without this, filtering data with local dataset will not always show correctly
// also don't use "invalidateRows" since it destroys the entire row and as bad user experience when updating a row
// see commit: https://github.com/ghiscoding/Angular-Slickgrid/commit/bb62c0aa2314a5d61188ff005ccb564577f08805
- if (gridOptions && gridOptions.enableFiltering) {
+ if (gridOptions && gridOptions.enableFiltering && !gridOptions.enableRowDetailView) {
this._eventHandler.subscribe(dataView.onRowsChanged, (e: any, args: any) => {
if (args && args.rows && Array.isArray(args.rows)) {
args.rows.forEach((row) => grid.updateRow(row));
diff --git a/src/app/modules/angular-slickgrid/filters/autoCompleteFilter.ts b/src/app/modules/angular-slickgrid/filters/autoCompleteFilter.ts
index 036308d1d..02af97ed9 100644
--- a/src/app/modules/angular-slickgrid/filters/autoCompleteFilter.ts
+++ b/src/app/modules/angular-slickgrid/filters/autoCompleteFilter.ts
@@ -58,7 +58,7 @@ export class AutoCompleteFilter implements Filter {
return this.columnDef && this.columnDef.filter && this.columnDef.filter.collectionOptions || {};
}
- /** Getter for the Filter Operator */
+ /** Getter for the Column Filter */
get columnFilter(): ColumnFilter {
return this.columnDef && this.columnDef.filter || {};
}
diff --git a/src/app/modules/angular-slickgrid/filters/compoundDateFilter.ts b/src/app/modules/angular-slickgrid/filters/compoundDateFilter.ts
index cf34905bc..cd2f0452c 100644
--- a/src/app/modules/angular-slickgrid/filters/compoundDateFilter.ts
+++ b/src/app/modules/angular-slickgrid/filters/compoundDateFilter.ts
@@ -41,14 +41,17 @@ export class CompoundDateFilter implements Filter {
return (this.grid && this.grid.getOptions) ? this.grid.getOptions() : {};
}
- /** Getter for the Filter Operator */
+ /** Getter for the Column Filter */
get columnFilter(): ColumnFilter {
return this.columnDef && this.columnDef.filter || {};
}
+ /** Setter for the Filter Operator */
set operator(op: OperatorType | OperatorString) {
this._operator = op;
}
+
+ /** Getter for the Filter Operator */
get operator(): OperatorType | OperatorString {
return this._operator || OperatorType.empty;
}
diff --git a/src/app/modules/angular-slickgrid/filters/compoundInputFilter.ts b/src/app/modules/angular-slickgrid/filters/compoundInputFilter.ts
index b55671dea..32873d977 100644
--- a/src/app/modules/angular-slickgrid/filters/compoundInputFilter.ts
+++ b/src/app/modules/angular-slickgrid/filters/compoundInputFilter.ts
@@ -34,7 +34,7 @@ export class CompoundInputFilter implements Filter {
return (this.grid && this.grid.getOptions) ? this.grid.getOptions() : {};
}
- /** Getter for the Filter Operator */
+ /** Getter for the Column Filter */
get columnFilter(): ColumnFilter {
return this.columnDef && this.columnDef.filter || {};
}
diff --git a/src/app/modules/angular-slickgrid/filters/inputFilter.ts b/src/app/modules/angular-slickgrid/filters/inputFilter.ts
index 81c5eae55..74d043eb1 100644
--- a/src/app/modules/angular-slickgrid/filters/inputFilter.ts
+++ b/src/app/modules/angular-slickgrid/filters/inputFilter.ts
@@ -24,7 +24,7 @@ export class InputFilter implements Filter {
constructor() {}
- /** Getter for the Filter Operator */
+ /** Getter for the Column Filter */
get columnFilter(): ColumnFilter {
return this.columnDef && this.columnDef.filter || {};
}
diff --git a/src/app/modules/angular-slickgrid/formatters/complexObjectFormatter.ts b/src/app/modules/angular-slickgrid/formatters/complexObjectFormatter.ts
index 9298e2bc4..f8e640c04 100644
--- a/src/app/modules/angular-slickgrid/formatters/complexObjectFormatter.ts
+++ b/src/app/modules/angular-slickgrid/formatters/complexObjectFormatter.ts
@@ -7,11 +7,18 @@ export const complexObjectFormatter: Formatter = (row: number, cell: number, val
}
const columnParams = columnDef.params || {};
- const complexField = columnParams && columnParams.complexField || columnDef.field;
+ const complexFieldLabel = columnParams && columnParams.complexFieldLabel || columnDef.field;
+
+ if (!complexFieldLabel) {
+ throw new Error(`For the Formatters.complexObject to work properly, you need to tell it which property of the complex object to use.
+ You can provide via 2 ways:
+ 1- via the generic "params" with a "complexFieldLabel" property on your Column Definition, example: this.columnDefs = [{ id: 'user', field: 'user', params: { complexFieldLabel: 'user.firstName' } }]
+ 2- via the field name that includes a dot notation, example: this.columnDefs = [{ id: 'user', field: 'user.firstName'}] `);
+ }
if (columnDef.labelKey) {
- return dataContext[complexField] && dataContext[complexField][columnDef.labelKey];
+ return dataContext[complexFieldLabel] && dataContext[complexFieldLabel][columnDef.labelKey];
}
- return complexField.split('.').reduce((obj, i) => (obj ? obj[i] : ''), dataContext);
+ return complexFieldLabel.split('.').reduce((obj, i) => (obj ? obj[i] : ''), dataContext);
};
diff --git a/src/index.html b/src/index.html
index ccbd1fbae..2ac2fe06d 100644
--- a/src/index.html
+++ b/src/index.html
@@ -8,7 +8,7 @@
-
+