Skip to content
This repository was archived by the owner on Jun 1, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
<a [routerLink]="['/rowdetail']">21- Row Detail View</a>
</li>
<li routerLinkActive="active">
<a [routerLink]="['/angular-components']">22- Editors Angular Components</a>
<a [routerLink]="['/angular-components']">22- Use of Angular Components</a>
</li>
</ul>
</div>
Expand Down
3 changes: 3 additions & 0 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { AppComponent } from './app.component';
import { CustomTitleFormatterComponent } from './examples/custom-titleFormatter.component';
import { EditorNgSelectComponent } from './examples/editor-ng-select.component';
import { FilterNgSelectComponent } from './examples/filter-ng-select.component';
import { GridAddItemComponent } from './examples/grid-additem.component';
import { GridBasicComponent } from './examples/grid-basic.component';
import { GridClientSideComponent } from './examples/grid-clientside.component';
Expand Down Expand Up @@ -74,6 +75,7 @@ export function appInitializerFactory(translate: TranslateService, injector: Inj
AppComponent,
CustomTitleFormatterComponent,
EditorNgSelectComponent,
FilterNgSelectComponent,
GridAddItemComponent,
GridAngularComponent,
GridBasicComponent,
Expand Down Expand Up @@ -129,6 +131,7 @@ export function appInitializerFactory(translate: TranslateService, injector: Inj
// dynamically created components
CustomTitleFormatterComponent,
EditorNgSelectComponent,
FilterNgSelectComponent,
RowDetailPreloadComponent,
RowDetailViewComponent,
],
Expand Down
24 changes: 16 additions & 8 deletions src/app/examples/custom-angularComponentEditor.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ComponentRef } from '@angular/core';
import { Subscription } from 'rxjs';
import {
AngularUtilService,
Column,
Expand All @@ -13,6 +14,8 @@ import {
* KeyDown events are also handled to provide handling for Tab, Shift-Tab, Esc and Ctrl-Enter.
*/
export class CustomAngularComponentEditor implements Editor {
changeSubscriber: Subscription;

/** Angular Component Reference */
componentRef: ComponentRef<any>;

Expand Down Expand Up @@ -41,7 +44,7 @@ export class CustomAngularComponentEditor implements Editor {

/** Get the Collection */
get collection(): any[] {
return this.columnDef && this.columnDef && this.columnDef.internalColumnEditor.collection || [];
return this.columnDef && this.columnDef.internalColumnEditor.collection || [];
}

/** Get Column Definition object */
Expand Down Expand Up @@ -70,17 +73,21 @@ export class CustomAngularComponentEditor implements Editor {

init() {
if (!this.columnEditor || !this.columnEditor.params.component || !(this.angularUtilService instanceof AngularUtilService)) {
throw new Error(`[Angular-Slickgrid] For the Editors.angularComponent to work properly, you need to provide your component to the "component" property and make sure to add it to your "entryComponents" array.
throw new Error(`[Angular-Slickgrid] For Editor with Angular Component to work properly, you need to provide your component to the "component" property and make sure to add it to your "entryComponents" array.
You also need to provide the "AngularUtilService" via the Editor Params OR the Grid Options Params
Example: this.columnDefs = [{ id: 'title', field: 'title', editor: { model: CustomAngularComponentEditor, collection: [...] }, params: { component: MyComponent, angularUtilService: this.angularUtilService }];
Example: this.columnDefs = [{ id: 'title', field: 'title', editor: { model: CustomAngularComponentEditor, collection: [...], params: { component: MyComponent, angularUtilService: this.angularUtilService }}];
OR this.columnDefs = [{ id: 'title', field: 'title', editor: { model: CustomAngularComponentEditor, collection: [...] }]; this.gridOptions = { params: { angularUtilService: this.angularUtilService }}`);
}
if (this.columnEditor && this.columnEditor.params.component) {
const componentOutput = this.angularUtilService.createAngularComponentAppendToDom(this.columnEditor.params.component, this.args.container);
this.componentRef = componentOutput && componentOutput.componentRef;

// here we override the collection object of the Angular Component
// but technically you can pass any values you wish to your Component
Object.assign(this.componentRef.instance, { collection: this.collection });

this.componentRef.instance.onModelChanged.subscribe((item) => {
// when our model (item object) changes, we'll call a save of the slickgrid editor
this.changeSubscriber = this.componentRef.instance.onItemChanged.subscribe((item) => {
this.save();
});
}
Expand All @@ -105,29 +112,30 @@ export class CustomAngularComponentEditor implements Editor {
}
}

/** optional, implement a hide method on your Angular Component */
hide() {
// optional, implement a hide method on your Angular Component
if (this.componentRef && this.componentRef.instance && typeof this.componentRef.instance.hide === 'function') {
this.componentRef.instance.hide();
}
}

/** optional, implement a show method on your Angular Component */
show() {
// optional, implement a show method on your Angular Component
if (this.componentRef && this.componentRef.instance && typeof this.componentRef.instance.show === 'function') {
this.componentRef.instance.show();
}
}

/** destroy the Angular Component & Subscription */
destroy() {
// destroy the Angular Component
if (this.componentRef && this.componentRef.destroy) {
this.componentRef.destroy();
this.changeSubscriber.unsubscribe();
}
}

/** optional, implement a focus method on your Angular Component */
focus() {
// optional, implement a focus method on your Angular Component
if (this.componentRef && this.componentRef.instance && typeof this.componentRef.instance.focus === 'function') {
this.componentRef.instance.focus();
}
Expand Down
118 changes: 118 additions & 0 deletions src/app/examples/custom-angularComponentFilter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { ComponentRef } from '@angular/core';
import { Subscription } from 'rxjs';
import {
AngularUtilService,
Column,
ColumnFilter,
Filter,
FilterArguments,
FilterCallback,
GridOption,
OperatorType,
OperatorString,
SearchTerm,
} from './../modules/angular-slickgrid';

// using external non-typed js libraries
declare var $: any;

export class CustomAngularComponentFilter implements Filter {
changeSubscriber: Subscription;

/** Angular Component Reference */
componentRef: ComponentRef<any>;

grid: any;
searchTerms: SearchTerm[];
columnDef: Column;
callback: FilterCallback;
operator: OperatorType | OperatorString = OperatorType.equal;

constructor() {}

/** Angular Util Service (could be inside the Grid Options Params or the Filter Params ) */
get angularUtilService(): AngularUtilService {
let angularUtilService = this.gridOptions && this.gridOptions.params && this.gridOptions.params.angularUtilService;
if (!angularUtilService || !(angularUtilService instanceof AngularUtilService)) {
angularUtilService = this.columnFilter && this.columnFilter.params && this.columnFilter.params.angularUtilService;
}
return angularUtilService;
}

/** Get the Collection */
get collection(): any[] {
return this.columnFilter && this.columnFilter.collection || [];
}

/** Getter for the Column Filter */
get columnFilter(): ColumnFilter {
return this.columnDef && this.columnDef.filter || {};
}

/** Getter for the Grid Options pulled through the Grid Object */
get gridOptions(): GridOption {
return (this.grid && this.grid.getOptions) ? this.grid.getOptions() : {};
}

/**
* Initialize the Filter
*/
init(args: FilterArguments) {
this.grid = args.grid;
this.callback = args.callback;
this.columnDef = args.columnDef;
this.searchTerms = args.searchTerms || [];

if (!this.columnFilter || !this.columnFilter.params.component || !(this.angularUtilService instanceof AngularUtilService)) {
throw new Error(`[Angular-Slickgrid] For Filter with Angular Component to work properly, you need to provide your component to the "component" property and make sure to add it to your "entryComponents" array.
You also need to provide the "AngularUtilService" via the Filter Params OR the Grid Options Params
Example: this.columnDefs = [{ id: 'title', field: 'title', filter: { model: CustomAngularComponentFilter, collection: [...], params: { component: MyComponent, angularUtilService: this.angularUtilService }}];
OR this.columnDefs = [{ id: 'title', field: 'title', filter: { model: CustomAngularComponentFilter, collection: [...] }]; this.gridOptions = { params: { angularUtilService: this.angularUtilService }}`);
}

if (this.columnFilter && this.columnFilter.params.component) {
// use a delay to make sure Angular ran at least a full cycle and it finished rendering the Component before hooking onto it
// else we get the infamous error "ExpressionChangedAfterItHasBeenCheckedError"
setTimeout(() => {
const $headerElm = this.grid.getHeaderRowColumn(this.columnDef.id);
$($headerElm).empty();
const componentOuput = this.angularUtilService.createAngularComponentAppendToDom(this.columnFilter.params.component, $headerElm);
this.componentRef = componentOuput.componentRef;

// here we override the collection object of the Angular Component
// but technically you can pass any values you wish to your Component
Object.assign(componentOuput.componentRef.instance, { collection: this.collection });

this.changeSubscriber = componentOuput.componentRef.instance.onItemChanged.subscribe((item) => {
this.callback(undefined, { columnDef: this.columnDef, operator: this.operator, searchTerms: [item.id] });
});
});
}
}

/**
* Clear the filter value
*/
clear() {
if (this.componentRef && this.componentRef.instance && this.componentRef.instance.hasOwnProperty('selectedId')) {
this.componentRef.instance.selectedId = 0;
}
}

/** destroy the Angular Component & Subscription */
destroy() {
if (this.componentRef && this.componentRef.destroy) {
this.componentRef.destroy();
this.changeSubscriber.unsubscribe();
}
}

/**
* Set value(s) on the DOM element
*/
setValues(values) {
if (this.componentRef && this.componentRef.instance && this.componentRef.instance.hasOwnProperty('selectedId')) {
this.componentRef.instance.selectedId = values;
}
}
}
2 changes: 1 addition & 1 deletion src/app/examples/custom-inputFilter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export class CustomInputFilter implements Filter {

constructor() {}

/** Getter for the Filter Operator */
/** Getter for the Column Filter */
get columnFilter(): ColumnFilter {
return this.columnDef && this.columnDef.filter || {};
}
Expand Down
4 changes: 2 additions & 2 deletions src/app/examples/editor-ng-select.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ export class EditorNgSelectComponent {
selectedId: string;
selectedItem: any;
collection; // this will be filled by the collection of your column definition
onModelChanged = new Subject<any>(); // object
onItemChanged = new Subject<any>(); // object

onChange(item: any) {
this.selectedItem = item;
this.onModelChanged.next(item);
this.onItemChanged.next(item);
}

focus() {
Expand Down
32 changes: 32 additions & 0 deletions src/app/examples/filter-ng-select.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Component } from '@angular/core';
import { Subject } from 'rxjs';

// the appendTo="body" (necessary for SlickGrid filter) requires the body to be position relative like so
// <body style="position: relative">
@Component({
template: `
<ng-select class="custom no-style-select"
[items]="collection"
bindValue="id"
bindLabel="name"
[clearable]="false"
appendTo="body"
(change)="onChange($event)"
[(ngModel)]="selectedId"
>
<ng-template ng-label-tmp ng-option-tmp let-item="item">
{{ item?.name }}
</ng-template>
</ng-select>`
})
export class FilterNgSelectComponent {
selectedId: string;
selectedItem: any;
collection; // this will be filled by the collection of your column definition
onItemChanged = new Subject<any>(); // object

onChange(item: any) {
this.selectedItem = item;
this.onItemChanged.next(item);
}
}
6 changes: 4 additions & 2 deletions src/app/examples/grid-angular.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ <h2>{{title}}</h2>
<br>

<div class="col-sm-6">
<label>autoEdit setting</label>
<label>autoEdit setting: </label>
<span id="radioAutoEdit">
<label class="radio-inline control-label" for="radioTrue">
<input type="radio" name="inlineRadioOptions" id="radioTrue" checked [value]="isAutoEdit" (change)="setAutoEdit(true)"> ON (single-click)
Expand All @@ -19,10 +19,12 @@ <h2>{{title}}</h2>
<i class="fa fa-undo"></i>
Undo last edit(s)
</button>
<button class="btn btn-default btn-sm" (click)="angularGrid.filterService.clearFilters()">Clear Filters</button>
<button class="btn btn-default btn-sm" (click)="angularGrid.sortService.clearSorting()">Clear Sorting</button>
<label class="checkbox-inline control-label" for="autoCommitEdit">
<input type="checkbox" id="autoCommitEdit" [value]="gridOptions.autoCommitEdit" (click)="changeAutoCommit()">
Auto Commit Edit
</label>
</label>
</span>
</div>
</div>
Expand Down
16 changes: 16 additions & 0 deletions src/app/examples/grid-angular.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
h3 {
font-style: normal;
color: #3d3d3d;
}
.subtitle {
font-size: 18px;
}
.ng-select.custom {
border:0px;
max-height: 27px;
border-radius: 0;
}
.ng-input {
padding-top: -4px !important;
padding-left: 4px !important;
}
Loading