npm package: @novin/cover-ag-grid-web
Description: wrapper implementation over ag-grid library based on novin-rayvarz's RDT system
Latest version: 1.0.38

# Novin@Cover-Ag-Grid-Web

novin@cover-ag-grid-web is a ui table library written for RDT system (Rayvar DataTable)

---

## Table of Content

- [Novin@Cover-Ag-Grid-Web](#novincover-ag-grid-web)
  - [Table of Content](#table-of-content)
  - [How to Install](#how-to-install)
  - [Quick Start](#quick-start)
    - [Local Grid :](#local-grid-)
    - [Remote Grid :](#remote-grid-)
  - [Filtering](#filtering)
    - [Example: Defining Filterable Column In Schema](#example-defining-filterable-column-in-schema)
    - [Example: LocalGrid Filtering](#example-localgrid-filtering)
    - [Example: RemoteGrid Filtering](#example-remotegrid-filtering)
  - [Sorting](#sorting)
    - [Example: Defining Sortable Column In Schema](#example-defining-sortable-column-in-schema)
    - [Example: LocalGrid Sorting](#example-localgrid-sorting)
    - [Example: RemoteGrid Sorting](#example-remotegrid-sorting)
  - [Editing](#editing)
    - [Example: Defining Editable Column In Schema](#example-defining-editable-column-in-schema)
      - [Example: Single Row Edit](#example-single-row-edit)
  - [Data Types](#data-types)
  - [All Build Options](#all-build-options)
  - [Methods](#methods)
  - [Selection](#selection)
    - [Schema](#schema)
    - [Example: Single Select](#example-single-select)
    - [Example: Multiple Select](#example-multiple-select)
    - [Example: Keep Track Of Selection List](#example-keep-track-of-selection-list)
  - [Pagination](#pagination)
    - [Example: Pagination](#example-pagination)
  - [Context Menu](#context-menu)
    - [Example: Context Menu](#example-context-menu)
  - [Event Listeners](#event-listeners)
    - [Example: Grid Event Listeners](#example-grid-event-listeners)
  - [Localization](#localization)
    - [Example: Localization](#example-localization)
  - [Cell Renderers](#cell-renderers)
  - [Cell Editors](#cell-editors)
  - [Action Bar](#action-bar)
    - [Example: Action Bar](#example-action-bar)
  - [Detail Panel](#detail-panel)
    - [Example: Detail Panel](#example-detail-panel)
  - [Toolbar](#toolbar)
    - [Example: Custom Toolbar Action](#example-custom-toolbar-action)
  - [Column Actions](#column-actions)
    - [Example: Column Actions](#example-column-actions)
  - [Styling](#styling)
  - [Type of Grids](#type-of-grids)
  - [Global Config](#global-config)

---

<a id="how-to-install"></a>

## How to Install

To install @novin/cover-ag-grid-web run command :

```
npm install @novin/cover-ag-grid-web
```

---

<a id="quick-start"></a>

## Quick Start

```typescript
import { Schema } from "@novin/cover-ag-grid-web/types";

type Entity = {
  id: string;
  firstName: string;
  lastName: string;
  age: number;
};

const schema: Schema<Entity> = {
  fields: [
    {
      fieldName: "id",
      isKey: true,
    },
    {
      fieldName: "firstName",
      title: "نام",
    },
    {
      fieldName: "lastName",
      title: "نام خانوادگی",
    },
    {
      fieldName: "age",
      title: "سن",
    },
  ],
  filters: [],
  sorts: [],
};
```

### Local Grid :

```typescript
import { LocalGrid } from "@novin/cover-ag-grid-web";
import "@novin/cover-ag-grid-web/dist/styles.css";

const element = document.getElementById("my-grid");

const grid = await new LocalGrid<Entity>(element)
  .schema(schema)
  .rows([
    { id: "1", firstName: "سنبله", lastName: "کاشی", age: 23 },
    { id: "2", firstName: "نیلوفر", lastName: "علم", age: 35 },
    { id: "3", firstName: "کامبیز", lastName: "دیرباز", age: "42" },
  ])
  .build();
```

### Remote Grid :

```typescript
import { RemoteGrid } from "@novin/cover-ag-grid-web";
import {
  RdtRequestModel,
  RdtResponseModel,
  StatusCode,
} from "@novin/cover-ag-grid-web/types";
import "@novin/cover-ag-grid-web/dist/styles.css";

const element = document.getElementById("my-grid");

const grid = await new RemoteGrid<Entity>(element)
  .schema(schema)
  .datasource(
    async (request: RdtRequestModel): Promise<RdtResponseModel<Entity>> => {
      await new Promise((res) => setTimeout(res, 2000)); // wait for 2 seconds
      return {
        rows: [
          { id: "1", firstName: "سنبله", lastName: "کاشی", age: 23 },
          { id: "2", firstName: "نیلوفر", lastName: "علم", age: 35 },
          { id: "3", firstName: "کامبیز", lastName: "دیرباز", age: "42" },
        ],
        isLastPage: false,
        status: StatusCode.SUCCESS,
      };
    }
  );
```

---

<a id="filtering"></a>

## Filtering

To enable filtering for a specific column, the filtering information should be included in [Schema.Filters](#schema-filters).

```typescript
type Schema<TData = any> = {
  fields: Array<Field<TData>>;
  filters: Array<Filter<TData>>;
  sorts: Array<Sort<TData>>;
};

type Filter<TData> = {
  fieldName: FieldProperty<TData>; // the field that has a column and user can work with its filter.
  filterName: FieldProperty<TData>; // the field that filter applies on.
  type: FilterType;
};

type FieldProperty<TData> = keyof TData;

type FilterType =
  | "EqualBy"
  | "NotEqualBy"
  | "Contains"
  | "NotContains"
  | "Unknown"
  | "LessThan"
  | "LessThanOrEqual"
  | "GreaterThan"
  | "GreaterThanOrEqual"
  | "Or"
  | "And";
```

Also column data type should be specified. (`Schema.Field.Type.Name`)

<div style="background-color: #2f3640;border-radius: 5px; padding: 10px;color: #f5f6fa;">

<span style="font-weight: bold;">Note : </span> For local grids, filtering is applied internally by Ag-Grid, but for remote grids, every change in filter instances, calls datasource with updated RDT request.

</div>

### Example: Defining Filterable Column In Schema

```typescript
const schema: Schema<Entity> = {
  fields: [
    {
      fieldName: "id",
      isKey: true,
    },
    {
      fieldName: "firstName",
      title: "نام",
      type: {
        name: "String",
      },
    },
    {
      fieldName: "lastName",
      title: "نام خانوادگی",
    },
    {
      fieldName: "age",
      title: "سن",
      type: {
        name: "Int",
      },
    },
  ],
  filters: [
    {
      fieldName: "firstName",
      filterName: "firstName",
      type: "EqualBy",
    },
    {
      fieldName: "age",
      filterName: "age",
      type: "GreaterThan",
    },
  ],
  sorts: [],
};
```

### Example: LocalGrid Filtering

- `firstName` column is filterable, it filters rows with equal value to filter value.
- `age` column is filterable, it filters rows with greater value than filter value.

```typescript
import { LocalGrid } from "@novin/cover-ag-grid-web"
import "@novin/cover-ag-grid-web/dist/styles.css"

const element = document.getElementById("my-grid")

const grid = await new LocalGrid(element)
  .schema(schema)
  .rows(...)
```

### Example: RemoteGrid Filtering

- `firstName` and `age` columns are filterable. by changing filters value, datasource gets called with new `request.filters` value.

```typescript
import { RemoteGrid } from "@novin/cover-ag-grid-web";
import "@novin/cover-ag-grid-web/dist/styles.css";

const element = document.getElementById("my-grid");

const grid = await new RemoteGrid(element)
  .schema(schema)
  .datasource(
    async (request: RdtRequestModel): Promise<RdtResponseModel<Entity>> => {
      request.filters.forEach((filter) => console.log({ filter }));
      // request to external source and return new values...
    }
  );
```

---

<a id="soring"></a>

## Sorting

To enable filtering for a specific column, the filtering information should be included in [Schema.Sorts](#schema-filters).

```typescript
type Schema<TData = any> = {
  fields: Array<Field<TData>>;
  filters: Array<Filter<TData>>;
  sorts: Array<Sort<TData>>;
};

type Sort<TData> = {
  fieldName: FieldProperty<TData>;
  type: SortType;
  order: OrderType;
};

type FieldProperty<TData> = keyof TData;

type SortType = "All" | "Asc" | "Desc";

enum OrderType {
  Asc,
  Desc,
  All,
}
```

<div style="background-color: #2f3640;border-radius: 5px; padding: 10px;color: #f5f6fa;">

<span style="font-weight: bold;">Note : </span> For local grids, sorting is applied internally by Ag-Grid, but for remote grids, every change in columns sorting, calls datasource with updated RDT request.

</div>

### Example: Defining Sortable Column In Schema

```typescript
const schema: Schema<Entity> = {
  fields: [
    {
      fieldName: "id",
      isKey: true,
    },
    {
      fieldName: "firstName",
      title: "نام",
    },
    {
      fieldName: "lastName",
      title: "نام خانوادگی",
    },
    {
      fieldName: "age",
      title: "سن",
    },
  ],
  filters: [],
  sorts: [
    {
      fieldName: "age",
      order: OrderType.Asc, // or simply 0
      type: "All",
    },
  ],
};
```

### Example: LocalGrid Sorting

- `age` column is sortable.

```typescript
import { LocalGrid } from "@novin/cover-ag-grid-web"
import "@novin/cover-ag-grid-web/dist/styles.css"

const element = document.getElementById("my-grid")

const grid = await new LocalGrid(element)
  .schema(schema)
  .rows(...)
```

### Example: RemoteGrid Sorting

- `age` column is sortable. by click on `age` column, column sorting changes and datasource gets called with new `request.orders` value.

```typescript
import { RemoteGrid } from "@novin/cover-ag-grid-web";
import "@novin/cover-ag-grid-web/dist/styles.css";

const element = document.getElementById("my-grid");

const grid = await new RemoteGrid(element)
  .schema(schema)
  .datasource(
    async (request: RdtRequestModel): Promise<RdtResponseModel<Entity>> => {
      request.orders.forEach((order) => console.log({ order }));
      // request to external source and return new values...
    }
  );
```

---

<a id="editing"></a>

## Editing

To enable editing for a column, use `isEditable` property on [field](#schema-fields) definition. Also [column data type](#data-) should be specified so grid can choose which cell editor to use.

### Example: Defining Editable Column In Schema

In the below schema :

- firstName is editable with default TextEditor
- lastName is editable with default TextEditor
- age is editable with default NumberEditor

```typescript
const schema: Schema<Entity> = {
  fields: [
    {
      fieldName: "id",
      isKey: true,
    },
    {
      fieldName: "firstName",
      title: "نام",
      isEditable: true,
      type: {
        name: "String",
      },
    },
    {
      fieldName: "lastName",
      title: "نام خانوادگی",
      isEditable: true,
      type: {
        name: "String",
      },
    },
    {
      fieldName: "age",
      title: "سن",
      isEditable: true,
      type: {
        name: "Int",
      },
    },
  ],
  filters: [],
  sorts: [],
};
```

Editing can be <ins>single-row</ins> or <ins>multiple-row</ins> (also known as bulk-edit) editing. At least one column should be editable to display the edit action button on the grid's [actions column](#column-actions). The final data of rows can be validated by using the [onEditRows](#editing-oneditrows) callback. If it returns `true`, then the grid will update the row values with new values. If it returns `false`, then the grid will abort the changes. If it does not return either `true` or `false`, the grid will assume that the changes are valid and will update the row data.

<a id="single-row-editing"></a>

- ### Single Row Editing

  By default, single-row editing is enabled in the grid after it finds at least one editable column in the grid schema. To enable row editing, the grid displays an `edit button` in the actions column for each row. Once row editing is enabled for a specific row, its every editable column will display its respective editor. After clicking the `edit button`, two new buttons will appear in the actions column:

  - Submit: This button submits the changes made to the row and exits the edit mode.
  - Cancel: This button cancels the changes made to the row and exits the edit mode.

  #### Example: Single Row Edit

  - `firstName`, `lastName` and `age` column are editable (`isEditable=true`)

  ```typescript
  import { LocalGrid } from "@novin/cover-ag-grid-web"
  import "@novin/cover-ag-grid-web/dist/styles.css"

  const element = document.getElementById("my-grid")

  const grid = await new LocalGrid<Entity>(element)
    .schema(schema)
    .rows(...)
    .build()
  ```

  <a id="multipe-row-editing"></a>

- ### Multiple Row Editing

  Multiple-row editing is only accessible through the grid API. The **startBulkEdit** method is used to activate bulk-edit mode. After changing the editing mode to bulk-edit, editing rows will not trigger the [onEditRows](#editing-oneditrows) callback until **finishBulkEdit** method is called.

  While editing rows in bulk-edit mode, an undo button will appear in every edited row's actions column, which aborts changes and resets the row's data to its initial value. The **finishBulkEdit** method is used to deactivate bulk-edit mode and call the [onEditRows](#editing-oneditrows) callback with changed values.

<a id="row-validation"></a>

- ### Row Validation

  You can prevent user from entering invalid values for columns while editing rows. row validation is possible in two ways:

  1. #### Validation Rules

     Validation rules can be defined via the `validation` method. You can define rules for each individual field and provide a validation function that gets called every time the field is changed. If the validation function returns a string, it means that the changed value is not valid, and the grid will display a tooltip error with the returned value as its error message. This allows users to see exactly what is wrong with their input and how to correct it.

     #### Example: Validation Rules

     - `firstName`, `lastName` and `age` column are editable (`isEditable=true`)

     ```typescript
     import { LocalGrid } from "@novin/cover-ag-grid-web"
     import "@novin/cover-ag-grid-web/dist/styles.css"

     const element = document.getElementById("my-grid")

     const grid = await new LocalGrid<Entity>(element)
       .schema(schema)
       .rows(...)
       .validation([
             {
               field: "age",
               validate(data) {
                 if (data.age >= 20) return "age can not be greater than 20";
               },
             },
             {
               field: "firstName",
               validate(data) {
                 if (data.firstName.startsWith("John"))
                   return "firstName cannot start with 'John'";
                 if (data.firstName.startsWith("Jane"))
                   return "firstName cannot start with 'Jane'";
               },
             },
         ])
       .fullRowEdit()
       .build()
     ```

     **OR**

     ```typescript
     import { LocalGrid } from "@novin/cover-ag-grid-web"
     import "@novin/cover-ag-grid-web/dist/styles.css"

     const element = document.getElementById("my-grid")

     const grid = await new LocalGrid<Entity>(element)
       .schema(schema)
       .rows(...)
       .validation([
           {
             validate(data, field) {
               switch (field) {
                 case "firstName":
                   if (data.firstName.startsWith("John"))
                     return "firstName cannot start with John'";
                   if (data.firstName.startsWith("Jane"))
                     return "firstName cannot start with 'Jane'";
                   break;
                 case "age":
                   if (data.age >= 20) return "age can not be greater than 20";
                   break;
               }
             },
           },
         ])
       .fullRowEdit()
       .build()
     ```

  2. #### onEditRows Callback

     grid calls `onEditRows` callback after finish editing and before submitting new data. If `onEditRows` returns `true`, grid apply changes and if it returns `false`, grid discard changes. If `onEditRows` does not return either `true` or `false`, <ins>grid apply changes</ins>.

     #### Example: onEditRows Callback

     ```typescript
     import { LocalGrid } from "@novin/cover-ag-grid-web"
     import "@novin/cover-ag-grid-web/dist/styles.css"

     const element = document.getElementById("my-grid")

     const grid = await new LocalGrid<Entity>(element)
      .schema(schema)
      .rows(...)
      .onEditRows(async (rows) => {
        console.log("new changes", rows)
        return true // return false (or nothing/void) to discard changes
      })
     ```

---

<a id="data-types"></a>

## Data Types

Six data types are supported by grid. Which means:

- The grid has default cell renderer for each type.
- The grid has default cell editor for each type.
- The grid has default filter for each type.
- The grid has default sorting mechanism for each type.

<div style="background-color: #2f3640;border-radius: 5px; padding: 10px;color: #f5f6fa;">

<span style="font-weight: bold;">Note : </span> If you want to use the default grid components for a column, you need to specify the column's type using the `Schema.Field.Type.Name` property. This allows the grid to determine which renderers, editors, and filters to use.

</div>

<a id="data-types-int"></a>

- ### Int

  > The **Int** type represents numeric value
  > <a id="data-types-string"></a>

- ### String

  The **String** type represents text value
  <a id="data-types-bit"></a>

- ### Bit

  The **Bit** type represents binary value. grid displays a checkbox as cell renderer and a two-option dropdown for filtering (with values `true`/`false`)
  <a id="data-types-date"></a>

- ### Date

  The **Date** type represents a date value. The grid tries to format the given value using the `Schema.Field.Properties.Format`. If no format is provided, the grid uses its default format to parse and render the value.

  - default date format : `YYYY/MM/DD`
    <a id="data-types-time"></a>

- ### Time

  The **Time** type represents a time value. The grid tries to format the given value using the `Schema.Field.Properties.Format`. If no format is provided, the grid uses its default format to parse and render the value.

  - default time format : `HHHH:mm:ss`
    <a id="data-types-list"></a>

- ### List
  The **List** type format represents a specific set of values that are available for that column. It's like a value source for a column. grid displays dropdown while editing **List** columns. list source must be defined through `Schema.Field.Type.Source` property. It can be a string (which represents an external source endpoint) or it can be an array of values (`TAutoCompleteItem<TData>[]`)

<div style="background-color: #2f3640;border-radius: 5px; padding: 10px;color: #f5f6fa;">

<span style="font-weight: bold;">Note : </span> If column source is an endpoint string, then columnSource function should be provided to grid, in this way grid can call columnSource with given endpoint to fetch items.

</div>

<a id="data-types-object"></a>

- ### Object
  -incomplete-

---

<a id="build-options"></a>

## All Build Options

| Option Name           | Description                                                                                                        |
| --------------------- | ------------------------------------------------------------------------------------------------------------------ |
| build                 | builds the grid with given options and return an instance                                                          |
| contextMenu           | define context menu items                                                                                          |
| suppressContextMenu   | disable context menu                                                                                               |
| cellRenderers         | define custom cell renderer for columns                                                                            |
| cellEditors           | define custom cell editor for columns                                                                              |
| validation            | define validation rules for row editing                                                                            |
| onCellClick           | cell is clicked                                                                                                    |
| onCellDoubleClick     | cell is double clicked                                                                                             |
| onRowClick            | row is clicked                                                                                                     |
| onRowDoubleClick      | row is double clicked                                                                                              |
| onEditRows            | row editing finished. return true to submit changes or false to discard changes.                                   |
| onDeleteRows          | deleting a row. return true to confirm deleting or false to prevent from deleting.                                 |
| onSchemaChange        | grid' schema has changed. The reason can be column resizing, change columns visibility or change columns ordering. |
| rowClassRules         | define rules to apply css classes to row elements.                                                                 |
| rowCssRules           | define rules to apply css properties to row elements.                                                              |
| cellCssRules          | define rules to apply css properties to cell elements.                                                             |
| localize              | define custom localization                                                                                         |
| schema                | RDT schema object                                                                                                  |
| fullRowEdit           | enable full row editing                                                                                            |
| defaultSelect         | select first row by default                                                                                        |
| selection             | set selection config                                                                                               |
| pagination            | set pagination mode ("infinite-scroll" "pagination")                                                               |
| actionBar             | define action bar component                                                                                        |
| detailPanelComponent  | define detail panel component for rows                                                                             |
| title                 | set title for grid                                                                                                 |
| isRowMaster           | if returns false, then detail panel component won't show for that specific row.                                    |
| suppressToolbar       | disable toolbar                                                                                                    |
| toolbarActions        | define custom toolbar actions                                                                                      |
| actions               | define custom actions for 'actions column'                                                                         |
| emptyPinnedRowOptions | empty pinned row options!                                                                                          |
| columnSource          | source function that grid uses to fetch dropdown values for `List` type columns                                    |
| nativeColumnDefs      | AgGrid ColDef definitions for columns                                                                              |
| defaultColDefs        | AgGrid defaultColDef                                                                                               |
| settings              | It is possible to pass most of the above parameters through `settings` function.                                   |

---

<a id="methods"></a>

## Methods

| Method Name                     | Description                                                                                                                                                                                                                                                                  |
| ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| getSchema                       | returns initial schema object                                                                                                                                                                                                                                                |
| getCurrentSchema                | returns current schema object                                                                                                                                                                                                                                                |
| getSelectedRows                 | returns an array of selected rows                                                                                                                                                                                                                                            |
| updateRows                      | directly update rows with given data, regardless of validations and onEditRows callback                                                                                                                                                                                      |
| selectRows                      | select rows                                                                                                                                                                                                                                                                  |
| deselectRows                    | deselect rows                                                                                                                                                                                                                                                                |
| deleteRows                      | delete rows. If onDeleteRows returns true, the rows will be removed from the grid. However, if onDeleteRows returns false, then the deletion process will be canceled. If onDeleteRows is not defined, the grid will continue deleting rows without asking for confirmation. |
| setLoading                      | enable or disable grid's loading                                                                                                                                                                                                                                             |
| addOnSelectionChangeListener    | subscribe to selection changes.                                                                                                                                                                                                                                              |
| removeOnSelectionChangeListener | unsubscribe to selection changes.                                                                                                                                                                                                                                            |
| setPageSize                     | change grid page size                                                                                                                                                                                                                                                        |
| startEditing                    | enable editing for a given row                                                                                                                                                                                                                                               |
| stopEditing                     | finish editing. onEditRows will get call if it is provided.                                                                                                                                                                                                                  |
| displayEmptyPinnedRow           | display empty pinned row at the top of grid (above all the rows)                                                                                                                                                                                                             |
| hideEmptyPinnedRow              | hide empty pinned row. inserted data will get removed from row.                                                                                                                                                                                                              |
| insertEmptyPinnedRowData        | If inserted values are not valid, it does nothing. Otherwise it calls onAdd on emptyPinnedRowOptions (if provided), if onAdd function returns `true`, new data will get inserted in grid, otherwise it will get ignored.                                                     |
| getEmptyPinnedRowData           | returns current inserted data in the empty pinned row                                                                                                                                                                                                                        |
| refreshToolbar                  | refresh toolbar component                                                                                                                                                                                                                                                    |
| getElement                      | returns grid html container element                                                                                                                                                                                                                                          |
| startBulkUpdate                 | enable bulk-edit mode                                                                                                                                                                                                                                                        |
| finishBulkUpdate                | disable bulk-edit mode. onEditRows will gets called with changes.                                                                                                                                                                                                            |
| restoreRowInitialData           | discard changed values while was editing and set row value to it's initial value.                                                                                                                                                                                            |
| getRowDataKey                   | returns row unique key.                                                                                                                                                                                                                                                      |
| getCurrentEditingRow            | returns current editing row                                                                                                                                                                                                                                                  |
| submitCurrentEditingRow         | finish editing current row.                                                                                                                                                                                                                                                  |
| isBulkEditEnabled               | returns `true` if grid is in bulk-edit mode, otherwise returns `false`                                                                                                                                                                                                       |
| isRowEdited                     | developers-only-method                                                                                                                                                                                                                                                       |
| setLatestAction                 | developers-only-method                                                                                                                                                                                                                                                       |
| isOptionalColumn                | developers-only-method                                                                                                                                                                                                                                                       |

---

<a id="selection"></a>

## Selection

Grid selection can be single-select or multiple-select.

- to enable single-selection, selection mode must be equal to "single"
- to enable multi-selection, selection mode must be equal to "multiple"
- by default, grid shows checkbox for selection. it can be disabled by setting checkbox property to `false`.
- for multi-selection grids, selectAll property can be set to `true` to display select all checkbox.

### Schema

```typescript
const schema: Schema<Entity> = {
  fields: [
    {
      fieldName: "id",
      isKey: true,
    },
    {
      fieldName: "firstName",
      title: "نام",
    },
    {
      fieldName: "lastName",
      title: "نام خانوادگی",
    },
    {
      fieldName: "age",
      title: "سن",
    },
  ],
  filters: [],
  sorts: [],
};
```

### Example: Single Select

```typescript
import { LocalGrid } from "@novin/cover-ag-grid-web"
import "@novin/cover-ag-grid-web/dist/styles.css"

const element = document.getElementById("my-grid")

const grid = await new LocalGrid<Entity>(element)
  .schema(schema)
  .rows(...)
  .selection({
    selection: "single",
    checkbox: true
  })
  .build()
```

### Example: Multiple Select

```typescript
import { LocalGrid } from "@novin/cover-ag-grid-web"
import "@novin/cover-ag-grid-web/dist/styles.css"

const element = document.getElementById("my-grid")

const grid = await new LocalGrid<Entity>(element)
  .schema(schema)
  .rows(...)
  .selection({
    selection: "multiple",
    checkbox: true,
    selectAll: true // optional
  })
  .build()
```

### Example: Keep Track Of Selection List

```typescript
type OnSelectionChangeArgs<TData> = {
  selectedList: Array<TData>;
};
type OnSelectionChange<TData> = (args: OnSelectionChangeArgs<TData>) => void;
```

```typescript
import { LocalGrid } from "@novin/cover-ag-grid-web"
import { OnSelectionChange } from "@novin/cover-ag-grid-web/types"
import "@novin/cover-ag-grid-web/dist/styles.css"

const element = document.getElementById("my-grid")

const grid = await new LocalGrid<Entity>(element)
  .schema(schema)
  .rows(...)
  .selection({
    selection: "multiple",
    checkbox: true,
    selectAll: true // optional
  })
  .build()

const onSelectionChange: OnSelectionChange<Entity> = ({ selectedList }) => {
  console.log("selection changed", selectedList)
}

grid.addOnSelectionChangeListener(onSelectionChange)

```

---

<a id="pagination"></a>

## Pagination

```typescript
type GridPaginationSetting = {
  paginationMode: "infiniteScroll" | "pagination";
  pageSize: number;
};
```

### Example: Pagination

```typescript
import { RemoteGrid } from "@novin/cover-ag-grid-web"
import "@novin/cover-ag-grid-web/dist/styles.css"

const element = document.getElementById("my-grid")

const grid = await new RemoteGrid<Entity>(element)
  .schema(schema)
  .datasource(...)
  .pagination({
    paginationMode: "infiniteScroll", // or "pagination"
    pageSize: 20
  })
  .build()
```

---

<a id="contex-meun"></a>

## Context Menu

```typescript
type GetContextMenuItems<TData> = (
  params: GetContextMenuItemsParams<TData>
) => ContextMenuItem[];
type GetContextMenuItemsParams<TData> = {
  gridInstance: LocalGrid<TData> | RemoteGrid<TData>;
  field: FieldProperty<TData>;
  rowData: TData;
};
type ContextMenuItem = string | AgGrid.MenuItemDef;
```

### Example: Context Menu

```typescript
import { LocalGrid } from "@novin/cover-ag-grid-web"
import "@novin/cover-ag-grid-web/dist/styles.css"

const element = document.getElementById("my-grid")

const grid = await new LocalGrid<Entity>(element)
  .schema(schema)
  .rows(...)
  .contextMenu((params: GetContextMenuItemsParams<Entity>) => {
    const { gridInstance, rowData, field } = params
    return [
      {
        name: rowData[field],
        action() {
          console.log({ rowData, field })
        }
      },
      {
        name: "Edit Row",
        action() {
          gridInstance.startEditing([rowData.userId])
        }
      }
    ]
  })
```

---

<a id="event-listeners"></a>

## Event Listeners

Grid supports variant of event listeners, based on Ag-Grid supported event listeners.

- onCellClick
- onCellDoubleClick
- onRowClick
- onRowDoubleClick

```typescript
type OnCellClick<TData> = (data: TData, field: string | undefined) => void;
type OnRowClick<TData> = (data: TData) => void;
```

### Example: Grid Event Listeners

```typescript
import { LocalGrid } from "@novin/cover-ag-grid-web"
import "@novin/cover-ag-grid-web/dist/styles.css"

const element = document.getElementById("my-grid")

const grid = await new LocalGrid<Entity>(element)
  .schema(schema)
  .rows(...)
  .onCellClick(params => {
    console.log("onCellClick", params)
  })
  .onCellDoubleClick(params => {
    console.log("onCellDoubleClick", params)
  })
  .onRowClick(params => {
    console.log("onRowClick", params)
  })
  .onRowDoubleClick(params => {
    console.log("onRowDoubleClick", params)
  })
  .build()
```

---

<a id="localization"></a>

## Localization

```typescript
type LocaleText = {
  submitEditAction?: string;
  cancelEditAction?: string;
  editRowAction?: string;
  restoreOriginRowDataAction?: string;
  deleteRowAction?: string;
  emptyCellPlaceholder?: string;
  requiredFieldError?: string;
  selectAll?: string;
  selectAllSearchResults?: string;
  searchOoo?: string;
  blanks?: string;
  noMatches?: string;
  filterOoo?: string;
  equals?: string;
  notEqual?: string;
  blank?: string;
  notBlank?: string;
  empty?: string;
  lessThan?: string;
  greaterThan?: string;
  lessThanOrEqual?: string;
  greaterThanOrEqual?: string;
  inRange?: string;
  inRangeStart?: string;
  inRangeEnd?: string;
  contains?: string;
  notContains?: string;
  startsWith?: string;
  endsWith?: string;
  dateFormatOoo?: string;
  andCondition?: string;
  orCondition?: string;
  applyFilter?: string;
  resetFilter?: string;
  clearFilter?: string;
  cancelFilter?: string;
  textFilter?: string;
  numberFilter?: string;
  dateFilter?: string;
  setFilter?: string;
  columns?: string;
  filters?: string;
  pivotMode?: string;
  groups?: string;
  rowGroupColumnsEmptyMessage?: string;
  values?: string;
  valueColumnsEmptyMessage?: string;
  pivots?: string;
  pivotColumnsEmptyMessage?: string;
  group?: string;
  rowDragRow?: string;
  rowDragRows?: string;
  loadingOoo?: string;
  noRowsToShow?: string;
  enabled?: string;
  pinColumn?: string;
  pinLeft?: string;
  pinRight?: string;
  noPin?: string;
  valueAggregation?: string;
  autosizeThiscolumn?: string;
  autosizeAllColumns?: string;
  groupBy?: string;
  ungroupBy?: string;
  addToValues?: string;
  removeFromValues?: string;
  addToLabels?: string;
  removeFromLabels?: string;
  resetColumns?: string;
  expandAll?: string;
  collapseAll?: string;
  copy?: string;
  ctrlC?: string;
  copyWithHeaders?: string;
  copyWithGroupHeaders?: string;
  paste?: string;
  ctrlV?: string;
  export?: string;
  csvExport?: string;
  excelExport?: string;
  sum?: string;
  min?: string;
  max?: string;
  none?: string;
  count?: string;
  avg?: string;
  filteredRows?: string;
  selectedRows?: string;
  totalRows?: string;
  totalAndFilteredRows?: string;
  more?: string;
  to?: string;
  of?: string;
  page?: string;
  nextPage?: string;
  lastPage?: string;
  firstPage?: string;
  previousPage?: string;
  pivotColumnGroupTotals?: string;
  pivotChartAndPivotMode?: string;
  pivotChart?: string;
  chartRange?: string;
  columnChart?: string;
  groupedColumn?: string;
  stackedColumn?: string;
  normalizedColumn?: string;
  barChart?: string;
  groupedBar?: string;
  stackedBar?: string;
  normalizedBar?: string;
  pieChart?: string;
  pie?: string;
  doughnut?: string;
  line?: string;
  xyChart?: string;
  scatter?: string;
  bubble?: string;
  areaChart?: string;
  area?: string;
  stackedArea?: string;
  normalizedArea?: string;
  histogramChart?: string;
  histogramFrequency?: string;
  combinationChart?: string;
  columnLineCombo?: string;
  AreaColumnCombo?: string;
  pivotChartTitle?: string;
  rangeChartTitle?: string;
  settings?: string;
  data?: string;
  format?: string;
  categories?: string;
  defaultCategory?: string;
  series?: string;
  xyValues?: string;
  paired?: string;
  axis?: string;
  navigator?: string;
  color?: string;
  thickness?: string;
  xType?: string;
  automatic?: string;
  category?: string;
  number?: string;
  time?: string;
  autoRotate?: string;
  xRotation?: string;
  yRotation?: string;
  ticks?: string;
  width?: string;
  height?: string;
  length?: string;
  padding?: string;
  spacing?: string;
  chart?: string;
  title?: string;
  titlePlaceholder?: string;
  background?: string;
  font?: string;
  top?: string;
  right?: string;
  bottom?: string;
  left?: string;
  labels?: string;
  size?: string;
  minSize?: string;
  maxSize?: string;
  legend?: string;
  position?: string;
  markerSize?: string;
  markerStroke?: string;
  markerPadding?: string;
  itemSpacing?: string;
  itemPaddingX?: string;
  itemPaddingY?: string;
  layoutHorizontalSpacing?: string;
  layoutVerticalSpacing?: string;
  strokeWidth?: string;
  lineDash?: string;
  offset?: string;
  offsets?: string;
  tooltips?: string;
  callout?: string;
  markers?: string;
  shadow?: string;
  blur?: string;
  xOffset?: string;
  yOffset?: string;
  lineWidth?: string;
  normal?: string;
  bold?: string;
  italic?: string;
  boldItalic?: string;
  predefined?: string;
  fillOpacity?: string;
  strokeOpacity?: string;
  histogramBinCount?: string;
  columnGroup?: string;
  barGroup?: string;
  pieGroup?: string;
  lineGroup?: string;
  scatterGroup?: string;
  areaGroup?: string;
  histogramGroup?: string;
  combinationGroup?: string;
  groupedColumnTooltip?: string;
  stackedColumnTooltip?: string;
  normalizedColumnTooltip?: string;
  groupedBarTooltip?: string;
  stackedBarTooltip?: string;
  normalizedBarTooltip?: string;
  pieTooltip?: string;
  doughnutTooltip?: string;
  lineTooltip?: string;
  groupedAreaTooltip?: string;
  stackedAreaTooltip?: string;
  normalizedAreaTooltip?: string;
  scatterTooltip?: string;
  bubbleTooltip?: string;
  histogramTooltip?: string;
  columnLineComboTooltip?: string;
  areaColumnComboTooltip?: string;
  customComboTooltip?: string;
  noDataToChart?: string;
  pivotChartRequiresPivotMode?: string;
  chartSettingsToolbarTooltip?: string;
  chartLinkToolbarTooltip?: string;
  chartUnlinkToolbarTooltip?: string;
  chartDownloadToolbarTooltip?: string;
  seriesChartType?: string;
  seriesType?: string;
  secondaryAxis?: string;
  ariaChecked?: string;
  ariaColumn?: string;
  ariaColumnGroup?: string;
  ariaColumnList?: string;
  ariaColumnSelectAll?: string;
  ariaDateFilterInput?: string;
  ariaDefaultListName?: string;
  ariaFilterColumnsInput?: string;
  ariaFilterFromValue?: string;
  ariaFilterInput?: string;
  ariaFilterList?: string;
  ariaFilterToValue?: string;
  ariaFilterValue?: string;
  ariaFilteringOperator?: string;
  ariaHidden?: string;
  ariaIndeterminate?: string;
  ariaInputEditor?: string;
  ariaMenuColumn?: string;
  ariaRowDeselect?: string;
  ariaRowSelectAll?: string;
  ariaRowToggleSelection?: string;
  ariaRowSelect?: string;
  ariaSearch?: string;
  ariaSortableColumn?: string;
  ariaToggleVisibility?: string;
  ariaUnchecked?: string;
  ariaVisible?: string;
  ariaSearchFilterValues?: string;
  ariaRowGroupDropZonePanelLabel?: string;
  ariaValuesDropZonePanelLabel?: string;
  ariaPivotDropZonePanelLabel?: string;
  ariaDropZoneColumnComponentDescription?: string;
  ariaDropZoneColumnValueItemDescription?: string;
  ariaDropZoneColumnGroupItemDescription?: string;
  ariaDropZoneColumnComponentAggFuncSeperator?: string;
  ariaDropZoneColumnComponentSortAscending?: string;
  ariaDropZoneColumnComponentSortDescending?: string;
  ariaLabelColumnMenu?: string;
  ariaLabelCellEditor?: string;
  ariaLabelDialog?: string;
  ariaLabelSelectField?: string;
  ariaLabelTooltip?: string;
  ariaLabelContextMenu?: string;
  ariaLabelSubMenu?: string;
  ariaLabelAggregationFunction?: string;
  thousandSeparator?: string;
  decimalSeparator?: string;
};
```

### Example: Localization

```typescript
import { LocalGrid } from "@novin/cover-ag-grid-web"
import "@novin/cover-ag-grid-web/dist/styles.css"

const element = document.getElementById("my-grid")

const grid = await new LocalGrid<Entity>(element)
  .schema(schema)
  .rows(...)
  .localize({
    noRowsToShow: "ردیفی یافت نشد"
  })
```

---

<a id="cell-renderers"></a>

## Cell Renderers

It is possible to override default render behavior for cell renderers. You can implement custom cell renderer for fields or more generally, types.

```typescript
type CellRenderer<TData> = {
  field: FieldProperty<TData>;
  renderer: typeof CustomCellRenderer<TData>;
};

abstract class CustomCellRenderer<TData> {
  abstract init(params: AgGrid.ICellRendererParams<TData>): void;
  abstract getGui(): HTMLElement;
  abstract refresh(params: AgGrid.ICellRendererParams<TData>): boolean;
  abstract destroy(): void;
}
```

<div style="background-color: #2f3640;border-radius: 5px; padding: 10px;color: #f5f6fa;">

<span style="font-weight: bold;">Note : </span> Please to figuring out how to implement a custom cell renderer, checkout Ag-Grid official documentation.

</div>

<a id="cell-editors"></a>

## Cell Editors

It is possible to override default editor behavior for cell editors. You can implement custom cell editor for fields or more generally, types.

```typescript
type CellEditor<TData> = {
  fieldOrType:
    | Field<TData>["fieldName"]
    | "string"
    | "number"
    | "boolean"
    | "date"
    | "time"
    | "object"
    | "list";
  editor: any; // AgGrid custom editor component
};
```

<div style="background-color: #2f3640;border-radius: 5px; padding: 10px;color: #f5f6fa;">

<span style="font-weight: bold;">Note : </span> Please to figuring out how to implement a custom cell editor, checkout Ag-Grid official documentation.

</div>

---

<a id="action-bar"></a>

## Action Bar

### Example: Action Bar

```typescript
import { LocalGrid } from "@novin/cover-ag-grid-web"
import "@novin/cover-ag-grid-web/dist/styles.css"

const element = document.getElementById("my-grid")

const grid = await new LocalGrid<Entity>(element)
  .schema(...)
  .rows(...)
  .selection({
    selection: "single",
    checkbox: false
  })
  .actionBar((gridInstance) => {
    const container = document.createElement("div");

    const addButton = document.createElement("button");
    addButton.innerHTML = "add";
    addButton.onclick = () => gridInstance.displayEmptyPinnedRow();

    const removeButton = document.createElement("button")
    removeButton.innerHTML = "remove"
    removeButton.onclick = () => {
      const selected = gridInstance.getSelectedRows()[0]
      if(selected) gridInstance.deleteRows([selected])
    }

    container.append(addButton, removeButton);

    return container;
  })
  .build();
```

---

<a id="detail-panel"></a>

## Detail Panel

it possible to render a html element as detail panel for rows.

### Example: Detail Panel

```typescript
import { LocalGrid } from "@novin/cover-ag-grid-web"
import "@novin/cover-ag-grid-web/dist/styles.css"

const element = document.getElementById("my-grid")

const grid = await new LocUsealGrid<Entity>(element)
  .schema(...)
  .rows(...)
  .detailPanelComponent((data, gridInstance) => {
    const container = document.createElement("div");
    container.innerHTML = `${data.firstName} + ${data.lastName} | ${data.age}`;
    return container;
  })
  .build()
```

Use `isRowMaster` callback to conditionally choose which rows have detail panel.

---

<a id="toolbar"></a>

## Toolbar

### Example: Custom Toolbar Action

```typescript
import { LocalGrid } from "@novin/cover-ag-grid-web"
import "@novin/cover-ag-grid-web/dist/styles.css"

const element = document.getElementById("my-grid")

const grid = await new LocalGrid<Entity>(element)
  .schema(...)
  .rows(...)
  .toolbarActions((defaults) => [
    ...defaults,
    {
      name: "custom-toolbar-action",
      icon: "print",
      async action(grid) {
        const selectedList = grid.getSelectedRows();
        console.log({ selectedList });
      },
    },
  ])
  .build()
```

---

<a id="column-actions"></a>

## Column Actions

### Example: Column Actions

```typescript
import { LocalGrid } from "@novin/cover-ag-grid-web"
import "@novin/cover-ag-grid-web/dist/styles.css"

const element = document.getElementById("my-grid")

const grid = await new LocalGrid<Entity>(element)
  .schema(...)
  .rows(...)
  .actions((defaults) => [
    ...defaults,
    {
      title: "print",
      action(event) {
        const selectedList = event.grid.getSelectedRows();
        console.log({ selectedList });
      },
    },
  ])
  .build()
```

---

<a id="styling"></a>

## Styling

<a id="styling-row-class"></a>

- ### Example: Row Class Rules

```typescript
import { LocalGrid } from "@novin/cover-ag-grid-web"
import "@novin/cover-ag-grid-web/dist/styles.css"

const element = document.getElementById("my-grid")

const grid = await new LocalGrid<Entity>(element)
  .schema(...)
  .rows(...)
  .rowClassRules({
    "disabled-row": row => row.age >= 50
  })
  .build()
```

<a id="styling-row-css"></a>

- ### Example: Row Css Rules

```typescript
import { LocalGrid } from "@novin/cover-ag-grid-web"
import "@novin/cover-ag-grid-web/dist/styles.css"

const element = document.getElementById("my-grid")

const grid = await new LocalGrid<Entity>(element)
  .schema(...)
  .rows(...)
  .rowCssRules([
      {
        rule(data, grid) {
          return data.age >= 50
        },
        styles: {
          color: "gray"
        }
      }
    ])
  .build()
```

<a id="styling-cell-css"></a>

- ### Example: Cell Css Rules

```typescript
import { LocalGrid } from "@novin/cover-ag-grid-web"
import "@novin/cover-ag-grid-web/dist/styles.css"

const element = document.getElementById("my-grid")

const grid = await new LocalGrid<Entity>(element)
  .schema(...)
  .rows(...)
  .cellCssRules([
    {
      field: "firstName",
      rule(data, field, grid) {
        return data.firstName == "John"
      },
      styles: {
        fontWeight: "bold"
      }
    }
  ])
  .build()
```

---

<a id="grid-types"></a>

## Type of Grids

<a id="remote-grid"></a>

- ### RemoteGrid

  Remote grids have external datasource for collecting rows to display in grid. a `datasource` function need to be provided for `RemoteGrid` class to fetch rows.

  Each action that requires loading new rows, calls `datasource` function. Like filtering, sorting, changing pagination...

<a id="local-grid"></a>

- ### LocalGrid

  Local grids have internal values (client-side) for rows.
  You can provide initial values by `rows(...)` function to grid or simply call `setRows(...)` after building grid instance.

  In local grids, all data handling happens in client-side. Like filtering, sorting and CRUD operations.

---

<a id="global-config"></a>

## Global Config

- setCellCssRules
- setCellEditors
- setCellValidations
- setColumnActions
- setLocaleText
- setSettings
- setToolbarActions

---