### Clone and Run Angular-Slickgrid Demo Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/README.md Clone the Angular-Slickgrid demos repository, navigate to a specific demo directory, install dependencies, and start the development server. ```sh git clone https://github.com/ghiscoding/angular-slickgrid-demos cd bootstrap5-demo-with-translate # or any of the other demos npm install npm start ``` -------------------------------- ### Regular Installation of ngx-translate Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/localization/Localization-with-ngx-translate.md Install ngx-translate core and the recommended http-loader. This setup is for regular usage where translations are loaded from external files. ```bash npm install @ngx-translate/core @ngx-translate/http-loader ## OR with yarn yarn add @ngx-translate/core @ngx-translate/http-loader ``` -------------------------------- ### Install Angular-Slickgrid and Bootstrap Source: https://context7.com/ghiscoding/angular-slickgrid/llms.txt Install the Angular-Slickgrid package and optional Bootstrap CSS for styling. ```bash npm install angular-slickgrid bootstrap # bootstrap is optional ``` -------------------------------- ### Angular Component Setup Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/events/Grid-&-DataView-Events.md Basic setup for an Angular component using Angular-Slickgrid, including event handlers and grid manipulation methods. ```typescript import { AngularGridInstance, Column, GridOption } from 'angular-slickgrid'; export class MyApp { angularGrid: AngularGridInstance; columnDefinitions: Column[]; gridOptions: GridOption; dataset: any[]; isAutoEdit = true; gridObj: any; dataViewObj: any; angularGridReady(angularGrid: AngularGridInstance) { this.angularGrid = angularGrid; this.gridObj = angularGrid.slickGrid; this.dataViewObj = angularGrid.dataView; } /** Change dynamically `autoEdit` grid options */ setAutoEdit(isAutoEdit) { this.isAutoEdit = isAutoEdit; this.gridObj.setOptions({ autoEdit: isAutoEdit }); // change the grid option dynamically return true; } collapseAllGroups() { this.dataviewObj.collapseAllGroups(); } expandAllGroups() { this.dataviewObj.expandAllGroups(); } } ``` -------------------------------- ### Install Angular-Slickgrid NPM Package Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/getting-started/quick-start.md Install the Angular-Slickgrid package and optional Bootstrap dependency using npm. ```bash npm install --save angular-slickgrid bootstrap # the last dep is optional ``` -------------------------------- ### Install Dependencies with Yarn Classic Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/CONTRIBUTING.md Install project dependencies using Yarn classic. Ensure you have Yarn classic installed. ```sh # step 1, install with Yarn classic yarn install ``` -------------------------------- ### Install Angular-Slickgrid Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/README.md Install the Angular-Slickgrid package using npm. This is the first step to integrate the data grid into your Angular application. ```sh npm install angular-slickgrid ``` -------------------------------- ### Run in Development Mode Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/CONTRIBUTING.md Start the development server to test your code changes. This command also runs tests. ```sh # step 2, run in dev and test your code change yarn start ``` -------------------------------- ### Basic Grid Component Setup Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/getting-started/quick-start.md Define column definitions, grid options, and dataset for a basic Angular-Slickgrid component. ```typescript import { Column, GridOption } from 'angular-slickgrid'; export class GridBasicComponent { columnDefinitions: Column[] = []; gridOptions: GridOption = {}; dataset: any[] = []; constructor() { this.prepareGrid(); } prepareGrid() { this.columnDefinitions = [ { id: 'title', name: 'Title', field: 'title', sortable: true }, { id: 'duration', name: 'Duration (days)', field: 'duration', sortable: true }, { id: '%', name: '% Complete', field: 'percentComplete', sortable: true }, { id: 'start', name: 'Start', field: 'start' }, { id: 'finish', name: 'Finish', field: 'finish' }, ]; this.gridOptions = { enableAutoResize: true, enableSorting: true }; // fill the dataset with your data (or read it from the DB) this.dataset = [ { id: 0, title: 'Task 1', duration: 45, percentComplete: 5, start: '2001-01-01', finish: '2001-01-31' }, { id: 1, title: 'Task 2', duration: 33, percentComplete: 34, start: '2001-01-11', finish: '2001-02-04' }, ]; } } ``` -------------------------------- ### Angular-Slickgrid Component Setup Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/column-functionalities/Editors.md Basic HTML structure for an Angular-Slickgrid component, including event bindings for editor-related actions. ```html
``` -------------------------------- ### Context Menu MenuUsabilityOverride Example Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/grid-functionalities/Context-Menu.md Dynamically control the availability of the entire context menu using `menuUsabilityOverride`. This example restricts the menu to the first 20 rows. ```typescript contextMenu: { menuUsabilityOverride: (args) => { const dataContext = args && args.dataContext; return (dataContext.id < 21); // say we want to display the menu only from Task 0 to 20 }, } ``` -------------------------------- ### Users Demo JSON Result (with Pagination) Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/backend-services/graphql/GraphQL-JSON-Result.md Example of a JSON response for a 'users' dataset when pagination is enabled. It includes 'totalCount' and an array of 'nodes'. ```json { "data": { "users": { "totalCount": 2, "nodes": [ { "id": 0, "firstName": "John", "lastName": "Doe", "email": "john@doe.com" }, { "id": 1, "firstName": "Jane", "lastName": "Doe", "email": "john@doe.com" } ] } } } ``` -------------------------------- ### Get Tree Data State Example Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/grid-functionalities/tree-data-grid.md Demonstrates how to retrieve the current toggled state of the tree data. This is useful for debugging or persisting the tree's expanded/collapsed state. ```typescript export class Example1 { angularGrid?: AngularGridInstance; angularGridReady(angularGrid: AngularGridInstance) { this.angularGrid = angularGrid; } getTreeDataState() { // for example get current Tree Data toggled state console.log(this.angularGrid.getCurrentToggleState()); } } ``` -------------------------------- ### Minimal ngx-translate Installation Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/localization/Localization-with-ngx-translate.md Install the ngx-translate core package. This is the minimum required if you intend to use ngx-translate with Angular-Slickgrid. ```typescript npm install @ngx-translate/core ``` -------------------------------- ### Angular-Slickgrid Component Setup Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/column-functionalities/filters/autocomplete-filter-kraaden-lib.md Basic HTML structure for an Angular-Slickgrid component. Ensure the grid options and column definitions are properly bound. ```html ``` -------------------------------- ### Basic Grid Setup in Angular Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/README.md Defines column definitions, dataset, and grid options for a basic Angular-Slickgrid component. Ensure 'OnInit' lifecycle hook is used for initialization. ```typescript import { type Column, type GridOption } from 'angular-slickgrid'; export class GridComponent implements OnInit { columnDefinitions: Column[] = []; gridOptions: GridOption; dataset: any[] = []; onInit() { this.columnDefinitions = [ { id: 'firstName', name: 'First Name', field: 'firstName', sortable: true }, { id: 'lastName', name: 'Last Name', field: 'lastName', sortable: true }, { id: 'age', name: 'Age', field: 'age', type: 'number', sortable: true } ]; this.dataset = [ { id: 1, firstName: 'John', lastName: 'Doe', age: 20 }, { id: 2, firstName: 'Jane', lastName: 'Smith', age: 21 } ]; this.gridOptions = { /*...*/ }; // optional grid options } } ``` -------------------------------- ### Run E2E Tests with Cypress Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/CONTRIBUTING.md Open the Cypress UI to run end-to-end tests. You can run all specs or select specific examples. ```sh # step 4, to test the E2E tests with Cypress the E2E tests yarn cypress:open # open Cypress UI then click on "Run All Specs" or choose dedicated Example to test ``` -------------------------------- ### GraphQL FilterBy Example Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/backend-services/graphql/GraphQL-Filtering.md Demonstrates how to filter users by first name using the `filterBy` argument with the `StartsWith` operator. ```graphql users (first: 20, offset: 10, filterBy: [{field: firstName, operator: StartsWith, value: 'John'}]) { totalCount nodes { name firstName lastName gender } } ``` -------------------------------- ### HTML Container for Resizing Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/grid-functionalities/Grid-Auto-Resize.md Example of an HTML structure where the grid is placed inside a container that can be resized. The `resize:both; overflow:auto;` styles enable manual resizing of the container. ```html
``` -------------------------------- ### Users Demo JSON Result (without Pagination) Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/backend-services/graphql/GraphQL-JSON-Result.md Example of a JSON response for a 'users' dataset when pagination is disabled. The 'users' key directly maps to an array of user objects. ```json { "data": { "users": [ { "id": 0, "firstName": "John", "lastName": "Doe", "email": "john@doe.com" }, { "id": 1, "firstName": "Jane", "lastName": "Doe", "email": "john@doe.com" } ] } } ``` -------------------------------- ### GraphQL Query with orderBy Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/backend-services/graphql/GraphQL-Sorting.md Example of a GraphQL query demonstrating the `orderBy` argument with multiple sorting criteria. The `orderBy` array specifies the field and direction for sorting. ```graphql users (first: 20, offset: 10, orderBy: [{field: lastName, direction: ASC}, {field: firstName, direction: DESC}]) { totalCount nodes { name firstName lastName gender } } ``` -------------------------------- ### Build Website Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/CONTRIBUTING.md Optionally build the project's website. This command compiles the demo website. ```sh # step 3.b, optional website build as well yarn build:demo ``` -------------------------------- ### Setup and Open Composite Editor Modal (TypeScript) Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/grid-functionalities/Composite-Editor-Modal.md Demonstrates how to set up the grid options to enable the composite editor and how to open the modal for creating a new item. Ensure `enableAddRow` is enabled for create/clone operations. The `registerExternalResources` option is used to include the composite editor instance. ```typescript import { Column, CompositeEditorModalType } from 'angular-slickgrid'; import { SlickCompositeEditorComponent } from '@slickgrid-universal/composite-editor-component'; example class MyCompositeDemo { compositeEditorInstance: SlickCompositeEditorComponent; constructor() { this.compositeEditorInstance = new SlickCompositeEditorComponent(); } prepareGrid() { this.columnDefinitions = [ /*...*/ ]; this.gridOptions = { enableAddRow: true, // required for Create/Clone enableCellNavigation: true, autoEdit: true, autoCommitEdit: true, enableCompositeEditor: true, registerExternalResources: [new ExcelExportService(), this.compositeEditorInstance], }; } openCompositeModal(modalType: CompositeEditorModalType = 'create') { // you can use a switch/case when using the Composite Modal for more than 1 modal type const modalTitle = 'Create Item'; this.compositeEditorInstance?.openDetails({ headerTitle: modalTitle, modalType, // insertNewId: 1234, // you can provide a custom Id (defaults to last Id+1) // insertOptions: { position: 'bottom' }, // if you wish to add the item to the bottom (defaults to top of the grid) onError: (error) => alert(error.message), // you should define how to deal with error coming from the modal // you can optionally provide an async callback method when dealing with a backend server onSave: (formValues, selection, dataContext) => { // simulate a backend server call which returns true (successful) after 30sec return new Promise(resolve => setTimeout(() => resolve(true), 500)); }); } } ``` -------------------------------- ### Multiple Select Editor with Async Collection Load Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/column-functionalities/Editors.md Load the collection for a `multipleSelect` editor asynchronously using `collectionAsync`. This example uses an Observable from an HTTP GET request to fetch the data. ```typescript this.columnDefinitions = [ { id: 'prerequisites', name: 'Prerequisites', field: 'prerequisites', filterable: true, editor: { collectionAsync: this.http.get<{ value: string; label: string; }[]>('api/data/pre-requisites'), model: Editors.multipleSelect, } } ]; ``` -------------------------------- ### Initialize Composite Editor Modal Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/grid-functionalities/Composite-Editor-Modal.md Set up the grid with `enableCompositeEditor` and register the `SlickCompositeEditorComponent`. Ensure columns intended for mass update have `massUpdate: true` in their editor configuration. ```typescript import { Column, CompositeEditorModalType, FieldType, Filters, Editors } from 'angular-slickgrid'; import { SlickCompositeEditorComponent } from '@slickgrid-universal/composite-editor-component'; import { ExcelExportService } from '@slickgrid-universal/excel-export'; example class MyCompositeDemo { compositeEditorInstance: SlickCompositeEditorComponent; columnDefinitions: Column[]; gridOptions: any; constructor() { this.compositeEditorInstance = new SlickCompositeEditorComponent(); } prepareGrid() { this.columnDefinitions = [ { id: 'percentComplete', name: '% Complete', field: 'percentComplete', type: FieldType.number, sortable: true, filterable: true, filter: { model: Filters.compoundSlider, operator: '>=' }, editor: { model: Editors.slider, massUpdate: true, // <-- this flag is required for Mass Update minValue: 0, maxValue: 100, }, }, ]; this.gridOptions = { enableCellNavigation: true, autoEdit: true, autoCommitEdit: true, enableCompositeEditor: true, registerExternalResources: [new ExcelExportService(), this.compositeEditorInstance], }; } openCompositeModal(modalType: CompositeEditorModalType = 'mass-update') { // you can use a switch/case when using the Composite Modal for more than 1 modal type const modalTitle = 'Mass Update'; this.compositeEditorInstance?.openDetails({ headerTitle: modalTitle, modalType, onError: (error) => alert(error.message), // you should define how to deal with error coming from the modal // you can optionally provide an async callback method when dealing with a backend server onSave: (formValues, selection, dataContext) => { // simulate a backend server call which returns true (successful) after 30sec return new Promise(resolve => setTimeout(() => resolve(true), 500)); }); } } ``` -------------------------------- ### Install ngx-translate for Angular 4-6 Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/localization/Localization-with-ngx-translate.md Install specific versions of ngx-translate core and http-loader for Angular versions 4-6. Adjust versions as needed for compatibility. ```bash npm install @ngx-translate/core@9.1.1 # change to the version that works for you npm install @ngx-translate/http-loader@2.0.0 # change to the version that works for you ``` -------------------------------- ### Context Menu ItemUsabilityOverride Example Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/grid-functionalities/Context-Menu.md Conditionally enable or disable context menu items using `itemUsabilityOverride`. This example enables the 'n/a' option only when the task is not completed. ```typescript contextMenu: { optionItems: [ { option: 0, title: 'n/a', textCssClass: 'italic', // only enable this option when the task is Not Completed itemUsabilityOverride: (args) => { const dataContext = args && args.dataContext; return !dataContext.completed; }, }, { option: 1, iconCssClass: 'mdi mdi-star-outline yellow', title: 'Low' }, { option: 2, iconCssClass: 'mdi mdi-star orange', title: 'Medium' }, { option: 3, iconCssClass: 'mdi mdi-star red', title: 'High' }, ] } ``` -------------------------------- ### Build Project (Library) Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/CONTRIBUTING.md Build the project's library (plugin). This command compiles the core Angular-Slickgrid components. ```sh # step 3.a, build plugin (lib) yarn build ``` -------------------------------- ### Frozen Rows Starting from Bottom Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/grid-functionalities/frozen-columns-rows.md To pin rows starting from the bottom, set `frozenBottom` to true in the grid options along with `frozenRow`. This allows rows to be fixed from the bottom edge of the grid. ```typescript import { Component, OnInit} from '@angular/core'; export class GridBasicComponent implements OnInit { columnDefinitions: Column[]; gridOptions: GridOption; dataset: any[]; ngOnInit(): void { // your columns definition this.columnDefinitions = []; this.gridOptions = { alwaysShowVerticalScroll: false, // disable scroll since we don't want it to show on the left pinned columns frozenColumn: 2, // number of pinned columns starting from the left frozenRow: 3, // number of pinned rows (starting from bottom with next property) frozenBottom: true, // this will make rows to be pinned starting from the bottom and the number of rows will be 3 } } } ``` -------------------------------- ### Initialize GraphqlService with Basic Options Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/backend-services/GraphQL.md Configure the GraphqlService with essential options for backend data processing, including dataset name and pagination settings. The `process` callback is used to define the API call for fetching data. ```typescript import { Component, Injectable, OnInit } from '@angular/core'; import { Column, GridOption } from 'angular-slickgrid'; import { GraphqlService, GraphqlPaginatedResult, GraphqlServiceApi, } from '@slickgrid-universal/graphql'; @Injectable() export class MyComponent implements OnInit { columnDefinitions: Column[]; gridOptions: GridOption; constructor(private http: HttpClient) { } ngOnInit(): void { this.columnDefinitions = [ // your column definitions ]; this.gridOptions = { enableFiltering: true, enablePagination: true, pagination: { pageSizes: [10, 15, 20, 25, 30, 40, 50, 75, 100], pageSize: defaultPageSize, totalItems: 0 }, backendServiceApi: { service: new GraphqlService(), // add some options to the backend service to work // shown below is the minimum setup for the service to work correctly options: { columnDefinitions: this.columnDefinitions, datasetName: 'users', paginationOptions: { first: 25, offset: 0 } }, // define all the on Event callbacks preProcess: () => this.displaySpinner(true), process: (query) => this.getAllCustomers(query), postProcess: (response) => this.displaySpinner(false) } }; } // Web API call getAllCustomers(graphqlQuery) { return this.http.post('/api/customers', { query: graphqlQuery }); } } ``` -------------------------------- ### Example Custom Formatter with HTML String Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/column-functionalities/Formatters.md Create a custom formatter function that returns an HTML string. This example uses SVG icons to display a 'fire' icon for true values and a 'snowflake' icon for false values, based on boolean input. ```typescript // create a custom Formatter with the Formatter type const myCustomCheckboxFormatter: Formatter = (row: number, cell: number, value: any, columnDef: Column, dataContext: any) => value ? `` : ''; ``` -------------------------------- ### Main Grid Component Setup for Row Detail View Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/grid-functionalities/row-detail.md Configure the main grid component to enable the row detail view. This involves setting 'enableRowDetailView' to true and pre-registering the 'SlickRowDetailView' extension. The 'rowDetailView' options specify how the detail panel should be processed and loaded. ```typescript import { Component, OnInit, ViewEncapsulation } from '@angular/core'; import { AngularGridInstance, Column, GridOption, GridState } from 'angular-slickgrid'; @Component({ styleUrls: ['main-grid.component.scss'], templateUrl: './main-grid.component.html', encapsulation: ViewEncapsulation.None, }) export class MainGridComponent implements OnInit { columnDefinitions: Column[] = []; gridOptions!: GridOption; angularGrid!: AngularGridInstance; dataset: Distributor[] = []; get rowDetailInstance(): SlickRowDetailView { return this.angularGrid.extensions.rowDetailView?.instance || {}; } angularGridReady(angularGrid: AngularGridInstance) { this.angularGrid = angularGrid; } ngOnInit(): void { this.defineGrid(); this.dataset = this.getData(); } defineGrid() { this.columnDefinitions = [ /*...*/ ]; this.gridOptions = { enableRowDetailView: true, rowSelectionOptions: { selectActiveRow: true }, preRegisterExternalExtensions: (pubSubService) => { // Row Detail View is a special case because of its requirement to create extra column definition dynamically // so it must be pre-registered before SlickGrid is instantiated, we can do so via this option const rowDetail = new SlickRowDetailView(pubSubService as EventPubSubService); return [{ name: ExtensionName.rowDetailView, instance: rowDetail }]; }, rowDetailView: { process: (item: any) => simulateServerAsyncCall(item), loadOnce: false, // IMPORTANT, you can't use loadOnce with inner grid because only HTML template are re-rendered, not JS events panelRows: 10, preloadComponent: PreloadComponent, viewComponent: InnerGridComponent, }, }; } } ``` -------------------------------- ### Apply lowerCase event naming convention Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/migrations/migration-to-3.x.md Example of how an event handler would change if `eventNamingStyle` is set to `lowerCase`. ```html ``` -------------------------------- ### Backend Service API Initialization Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/migrations/migration-to-2.x.md When using the `backendServiceApi`, the service should now be instantiated using `new` instead of being passed directly if it's not provided via dependency injection. ```diff export class MyGrid { - constructor(private graphqlService: GraphqlService, private i18n: I18N) { + constructor(private i18n: I18N) { } this.gridOptions = { backendServiceApi: { - service: this.graphqlService, + service: new GraphqlService(), preProcess: () => this.displaySpinner(true), process: (query) => this.getCustomerApiCall(query), postProcess: (result: GraphqlResult) => this.displaySpinner(false) }, params: { i18: this.translate } }; } ``` -------------------------------- ### Configure Angular Module for Root Source: https://context7.com/ghiscoding/angular-slickgrid/llms.txt Import AngularSlickgridModule.forRoot() in your AppModule for legacy NgModule setups or use importProvidersFrom for standalone applications. ```typescript // app.module.ts (legacy NgModule style) import { AngularSlickgridModule } from 'angular-slickgrid'; @NgModule({ imports: [AngularSlickgridModule.forRoot()], // forRoot() is REQUIRED }) export class AppModule {} // OR for Standalone / App Config style (Angular 14+): // app.config.ts import { ApplicationConfig, importProvidersFrom } from '@angular/core'; import { AngularSlickgridModule } from 'angular-slickgrid'; export const appConfig: ApplicationConfig = { providers: [ importProvidersFrom(AngularSlickgridModule.forRoot()), ], }; ``` -------------------------------- ### Basic Autocomplete Editor and Filter Configuration Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/column-functionalities/filters/autocomplete-filter-kraaden-lib.md Configure a column to use an autocomplete editor and filter. This example shows how to set up the `editor` and `filter` properties with `Editors.autocompleter` and `Filters.autocompleter` respectively, including asynchronous data fetching with `minLength` and a placeholder. ```typescript import { Component, OnInit} from '@angular/core'; export class GridBasicComponent implements OnInit { columnDefinitions: Column[]; gridOptions: GridOption; dataset: any[]; ngOnInit(): void { // your columns definition this.columnDefinitions = [ { id: 'cityOfOrigin', name: 'City of Origin', field: 'cityOfOrigin', filterable: true, minWidth: 100, editor: { model: Editors.autocompleter, placeholder: 'search city', // you can provide an optional placeholder to help your users // use your own autocomplete options, instead of $.ajax, use http // here we use $.ajax just because I'm not sure how to configure http with JSONP and CORS editorOptions: { minLength: 3, // minimum count of character that the user needs to type before it queries to the remote fetch: (searchText, updateCallback) => { // assuming your API call returns a label/value pair yourAsyncApiCall(searchText) // typically you'll want to return no more than 10 results .then(result => updateCallback((results.length > 0) ? results : [{ label: 'No match found.', value: '' }])) .catch(error => console.log('Error:', error)); } }, }, filter: { model: Filters.autocompleter, // placeholder: '🔍 search city', // 🔍 is a search icon, this provide an option placeholder // use your own autocomplete options, instead of $.ajax, use http // here we use $.ajax just because I'm not sure how to configure http with JSONP and CORS filterOptions: { minLength: 3, // minimum count of character that the user needs to type before it queries to the remote fetch: (searchText, updateCallback) => { // assuming your API call returns a label/value pair yourAsyncApiCall(searchText) // typically you'll want to return no more than 10 results .then(result => updateCallback((results.length > 0) ? results : [{ label: 'No match found.', value: '' }])) .catch(error => console.log('Error:', error)); }, } } } ]; this.gridOptions = { // your grid options config } } } ``` -------------------------------- ### Setup DataView Object Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/grid-functionalities/grouping-and-aggregators.md Retrieve the DataView object from the Angular-Slickgrid instance after it's created. This object is essential for configuring grouping and aggregators. ```typescript @Component({ templateUrl: './grid-grouping.component.html' }) export class GridGroupingComponent implements OnInit, OnDestroy { columnDefinitions: Column[]; gridOptions: GridOption; dataviewObj: any; angularGridReady(angularGrid: AngularGridInstance) { this.angularGrid = angularGrid; this.gridObj = angularGrid.slickGrid; this.dataViewObj = angularGrid.dataView; } } ``` -------------------------------- ### Grouping and Aggregators Source: https://context7.com/ghiscoding/angular-slickgrid/llms.txt This section demonstrates how to enable grouping and use various aggregators like Sum and Avg. It also shows how to define custom formatters for group totals and how to set up grid options for grouping. ```APIDOC ## Grouping and Aggregators Group rows and show aggregates (sum, avg, min, max). Requires `enableGrouping: true`. ```typescript import { Aggregators, Column, FieldType, Formatters, GroupTotalFormatters, SortComparers, SortDirectionNumber } from 'angular-slickgrid'; const columnDefinitions: Column[] = [ { id: 'title', field: 'title', name: 'Title' }, { id: 'duration', field: 'duration', name: 'Duration', type: FieldType.number, groupTotalsFormatter: GroupTotalFormatters.sumTotals, params: { groupFormatterPrefix: 'Total: ' } }, { id: 'cost', field: 'cost', name: 'Cost', formatter: Formatters.dollar, groupTotalsFormatter: GroupTotalFormatters.sumTotalsDollar, params: { groupFormatterPrefix: 'Total: ', groupFormatterSuffix: ' USD' } }, ]; const gridOptions = { enableGrouping: true, // Put the draggable grouping dropzone in the top-header panel (v8.1+) createTopHeaderPanel: true, showTopHeaderPanel: true, topHeaderPanelHeight: 35, }; // After angularGridReady, keep a reference to dataView: angularGridReady(angularGrid: AngularGridInstance) { this.angularGrid = angularGrid; this.dataViewObj = angularGrid.dataView; } groupByDuration() { this.dataViewObj.setGrouping({ getter: 'duration', formatter: (g) => `Duration: ${g.value} (${g.count} items)`, comparer: (a, b) => SortComparers.numeric(a.value, b.value, SortDirectionNumber.asc), aggregators: [ new Aggregators.Avg('percentComplete'), new Aggregators.Sum('cost'), ], aggregateCollapsed: false, lazyTotalsCalculation: true, }); } clearGrouping() { this.dataViewObj.setGrouping([]); } collapseAllGroups() { this.dataViewObj.collapseAllGroups(); } expandAllGroups() { this.dataViewObj.expandAllGroups(); } ``` ``` -------------------------------- ### App Module Configuration for ngx-translate Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/localization/Localization-with-ngx-translate.md Configure your AppModule to include TranslateModule for localization. This setup is necessary even if using only one locale. ```typescript import { NgModule } from '@angular/core'; import { TranslateModule } from '@ngx-translate/core'; import { AngularSlickgridModule } from 'angular-slickgrid'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, TranslateModule.forRoot() ], providers: [], bootstrap: [AppComponent] }) export class AppModule { } ``` -------------------------------- ### Initialize Grid with Sanitizer and Trusted Types Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/developer-guides/csp-compliance.md Initialize the Slicker Grid Bundle with the sanitizer configured to return trusted types. This ensures that HTML content is safely processed. ```typescript import DOMPurify from 'dompurify'; import { Slicker, SlickVanillaGridBundle } from '@slickgrid-universal/vanilla-bundle'; // DOM Purify is already configured in Slickgrid-Universal with the configuration shown below this.gridOptions = { sanitizer: (html) => DOMPurify.sanitize(html, { RETURN_TRUSTED_TYPE: true }), // you could also optionally use the sanitizerOptions instead // sanitizerOptions: { RETURN_TRUSTED_TYPE: true } } this.sgb = new Slicker.GridBundle(gridContainerElm, this.columnDefinitions, this.gridOptions, this.dataset); ``` -------------------------------- ### Implement Custom Title Validator Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/column-functionalities/Editors.md Example of a custom validator function for a 'title' field. It checks for required input and a specific format. ```typescript const myCustomTitleValidator: EditorValidator = (value: any, args: EditorArgs) => { // you can get the Editor Args which can be helpful, e.g. we can get the Translate Service from it const grid = args && args.grid; const columnDef = args.column; const dataContext = args.item; const gridOptions = (grid && grid.getOptions) ? grid.getOptions() : {}; const i18n = gridOptions.i18n; if (value == null || value === undefined || !value.length) { return { valid: false, msg: 'This is a required field' }; } else if (!/^Task\s\d+$/.test(value)) { return { valid: false, msg: 'Your title is invalid, it must start with "Task" followed by a number' }; // OR use the Translate Service with your custom message // return { valid: false, msg: i18n.tr('YOUR_ERROR', { x: value }) }; } else { return { valid: true, msg: '' }; } }; ``` -------------------------------- ### Define Cell Menu Options Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/column-functionalities/Cell-Menu.md Configure a cell menu with a list of options for the user to select. This example shows how to define options with titles, values, and icons, and includes a divider. The `action` callback is used to perform an action when an option is selected. ```typescript this.columnDefinitions = [ { id: 'firstName', field: 'firstName', name: 'First Name' }, { id: 'lastName', field: 'lastName', name: 'Last Name' }, // ... more column defs { id: 'action', name: 'Action', field: 'action', width: 110, maxWidth: 200, excludeFromExport: true, // you typically don't want this column exported formatter: actionFormatter, // your Custom Formatter cellMenu: { optionTitle: 'Change Effort Driven Flag', // optional, add title optionItems: [ { option: true, title: 'True', iconCssClass: 'mdi mdi-check-box-outline' }, { option: false, title: 'False', iconCssClass: 'mdi mdi-checkbox-blank-outline' }, { divider: true, command: '', positionOrder: 60 }, ], // subscribe to Context Menu onOptionSelected event (or use the "action" callback on each option) action: (e, args) => { console.log(args.dataContext, args.column); // action callback.. do something } } } ]; ``` -------------------------------- ### Basic GraphQL Query Structure Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/backend-services/graphql/GraphQL-Filtering.md Example of a GraphQL query with pagination and nested data fetching. Use dot notation for nested fields. ```typescript { users(first: 20, offset: 0, userId: 123) { totalCount, nodes { name, company, billing { address { street, zip } } } } } ``` -------------------------------- ### Enable Custom Footer with Options Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/grid-functionalities/Custom-Footer.md Enable the custom footer and configure its appearance with options like custom left text and hiding metrics. This setup is useful for displaying grid creation information and metrics. ```typescript defineGrid() { this.columnDefinitions = [ /*...*/ ]; this.gridOptions = { // ... showCustomFooter: true, // display some metrics in the bottom custom footer customFooterOptions: { // optionally display some text on the left footer container leftFooterText: 'Grid created with Slickgrid-Universal', hideMetrics: false, hideTotalItemCount: false, hideLastUpdateTimestamp: false }, }; } ``` -------------------------------- ### Instantiate Custom Backend Service in Grid Options Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/backend-services/Custom-Backend-Service.md Integrate your custom backend service by instantiating it directly within the grid options. This approach is suitable when the service is specific to the component's usage. ```typescript class MyComponent { gridInit() { this.gridOptions = { backendServiceApi: { service: new YourCustomBackendService(), options: { // custom service options that extends "backendServiceOption" interface }, preProcess: () => !this.isDataLoaded ? this.displaySpinner(true) : '', process: (query) => this.getCountries(query), postProcess: (result) => { this.displaySpinner(false); this.isDataLoaded = true; } } as YourCustomBackendServiceApi }; } } ``` -------------------------------- ### Instantiate Custom Backend Service Separately Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/backend-services/Custom-Backend-Service.md Instantiate your custom backend service in a separate variable and then pass it to the grid options. This is recommended for reusability and cleaner code structure. ```typescript class MyComponent { myCustomService = new YourCustomBackendService(); gridInit { this.gridOptions = { backendServiceApi: { service: this.myCustomService, // ... } as YourCustomBackendServiceApi }; } } ``` -------------------------------- ### Get Last Resize Dimensions Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/grid-functionalities/Grid-Auto-Resize.md The `resizeGrid()` method returns a promise that resolves with the last used dimensions, which can be used to synchronize the size of other elements. ```typescript async openSidebar() { this.isSidebarOpen = true; // resize the CPA list grid and resize the sidebar to the same height as the grid with it's pagination const lastDimensions = await this.sgb.resizerService.resizeGrid(); if (lastDimensions && lastDimensions.heightWithPagination) { this.sidebarMaxHeight = `${lastDimensions.heightWithPagination}px`; } } ``` -------------------------------- ### CSP Meta Tag Configuration Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/developer-guides/csp-compliance.md Example of a Content Security Policy meta tag that includes trusted types and specifies DOMPurify for enhanced security. ```html ``` -------------------------------- ### Basic Inline Editor Setup Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/column-functionalities/Editors.md Configure column definitions to use various inline editors like text, integer, date, and checkbox. Ensure `enableCellNavigation: true` and `editable: true` are set in Grid Options for editors to function. ```typescript this.columnDefinitions = [ { id: 'title', name: 'Title', field: 'title', type: FieldType.string, editor: { model: Editors.longText } }, { id: 'duration', name: 'Duration (days)', field: 'duration', type: FieldType.number, editor: { model: Editors.text } }, { id: 'complete', name: '% Complete', field: 'percentComplete', type: FieldType.number, editor: { model: Editors.integer } }, { id: 'start', name: 'Start', field: 'start', type: FieldType.date, editor: { model: Editors.date } }, { id: 'finish', name: 'Finish', field: 'finish', type: FieldType.date, editor: { model: Editors.date, // you can also add an optional placeholder placeholder: 'choose a date' } }, { id: 'effort-driven', name: 'Effort Driven', field: 'effortDriven', formatter: Formatters.checkmarkMaterial, type: FieldType.number, editor: { model: Editors.checkbox } } ]; this.gridOptions { enableCellNavigation: true, // <<-- VERY IMPORTANT, it won't work without this flag enabled editable: true, }; ``` -------------------------------- ### Toggle Dark Mode with setOptions Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/styling/dark-mode.md Demonstrates how to toggle dark mode using the `setOptions` method on the SlickGrid instance. This is useful for dynamic theme changes. ```typescript export class MyDemo { isDarkModeEnabled = false; gridOptions: GridOption; prepareGrid() { this.gridOptions = { // ... darkMode: this.isDarkModeEnabled; } } toggleDarkMode() { this.isDarkModeEnabled = !this.isDarkModeEnabled; this.sgb.slickGrid?.setOptions({ darkMode: this.isDarkModeEnabled }); // optionally update your local grid options as well this.gridOptions = { ...this.gridOptions, darkMode: this.isDarkModeEnabled }; } } ``` -------------------------------- ### Example GraphQL Query with Extra Arguments Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/backend-services/GraphQL.md Illustrates how the `extraQueryArguments` are incorporated into the final GraphQL query string. The `userId` argument is appended to the query parameters. ```graphql // extraQueryArguments will change the userId with { users(first: 20, offset: 0, userId: 567) { totalCount, nodes { id, name, company } } } ``` -------------------------------- ### Update Formatter Using DocumentFragment Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/migrations/migration-to-7.x.md This example demonstrates how to adapt a formatter that uses `Formatters.multiple` when dealing with native HTML elements or DocumentFragments. It shows creating a DocumentFragment and appending elements to it, ensuring compatibility with the new formatter output. ```typescript const priceFormatter: Formatter = (_cell, _row, value, _col, dataContext) => { const direction = dataContext.priceChange >= 0 ? 'up' : 'down'; - return ` ${value}`; + const fragment = document.createDocumentFragment(); + const spanElm = document.createElement('span'); + spanElm.className = `mdi mdi-arrow-${direction} color-${direction === 'up' ? 'success' : 'danger'}`; + fragment.appendChild(spanElm); + if (value instanceof HTMLElement) { + fragment.appendChild(value); + } + return fragment; }; init() { this.columnDefinitions = [ { id: 'priceChange', name: 'Change', field: 'priceChange', filterable: true, sortable: true, minWidth: 80, width: 80, filter: { model: Filters.compoundInputNumber }, type: FieldType.number, formatter: Formatters.multiple, params: { formatters: [Formatters.dollarColored, priceFormatter], maxDecimal: 2, } }, ], } ``` -------------------------------- ### Show Loading Spinner During Export Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/grid-functionalities/Export-to-Excel.md Display a loading spinner while the Excel export process is running. Use `onBeforeExportToExcel` to start the spinner and `onAfterExportToExcel` to stop it. ```html ``` ```typescript export class MyComponent() implements OnInit { processing = false; } ``` -------------------------------- ### Handling Angular Grid Creation Event Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/migrations/migration-to-2.x.md Use the `onAngularGridCreated` event to get the `AngularGridInstance` when the grid is ready. This instance provides access to grid services. ```diff ``` ```typescript export class MyGridDemo implements OnInit { + angularGrid: AngularGridInstance; columnDefinitions: Column[]; gridOptions: GridOption; dataset: any[]; - constructor(private GridExtraService) {} + angularGridReady(angularGrid: AngularGridInstance) { + this.angularGrid = angularGrid; + // Slick Grid & DataView objects + this.gridObj = angularGrid.slickGrid; + this.dataViewObj = angularGrid.dataView; + } addNewItem() { const newItem = { id: newId, title: 'Task ' + newId, effortDriven: true, // ... }; - this.gridExtraService.addItemToDatagrid(newItem); + this.angularGrid.gridService.addItemToDatagrid(newItem); } ``` -------------------------------- ### Override Checkbox SVG Icon Path with SASS Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/styling/styling.md A SASS-specific example for overriding just the SVG path for a checkbox icon, demonstrating a simpler approach compared to CSS. ```scss $slick-checkbox-icon-checked-svg-path: "M10,17L5,12L6.41,10.58L10,14.17L17.59,6.58L19,8M19,3H5C3.89,3 3,3.89 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3Z" ``` -------------------------------- ### Context Menu with Action Callback Source: https://github.com/ghiscoding/angular-slickgrid/blob/master/docs/grid-functionalities/Context-Menu.md Use the `action` callback to define specific logic for each command item in the context menu. This is suitable when each command has a unique, simple action. ```typescript contextMenu: { commandItems: [ { command: 'command1', title: 'Command 1', action: (e, args) => console.log(args) } { command: 'command2', title: 'Command 2', action: (e, args) => console.log(args) } // ... ] } ```