[![npm version](https://badge.fury.io/js/%40lucasheight%2Fkendo-grid-state.svg)](https://badge.fury.io/js/%40lucasheight%2Fkendo-grid-state)

# Angular kendo-grid-State directive

## Purpose

A helper library that implements a directive to manage grid state during session or between sessions for [@Progress Kendo UI for Angular Grid.](https://www.telerik.com/kendo-angular-ui)

## Compatibility

| Library version | Angular     | Kendo Angular Grid |
| --------------- | ----------- | ------------------ |
| 2.x             | 14 – 21     | 4 – 23             |
| 1.x             | 8 – 18      | 4 – 19             |

## Features

- State persistence is managed entirely in the directive.
- State storage can be session, local or custom. Defaults to session.
- Persists expanded rows.
- Persists column visibility.
- Persists column resize.
- Persists column reorder.
- Persists grid sort, page, page size, group, filter etc..

## How to use

### Install

Install the Angular library with NPM:

```
    npm install --save @lucasheight/kendo-grid-state
```

### Using the library — NgModule (Angular 12+)

Import `GridStateModule` into your NgModule:

```typescript
@NgModule({
  declarations: [AppComponent, GridDirectiveComponent],
  imports: [BrowserModule, BrowserAnimationsModule, CommonModule, HttpClientModule, GridModule, GridStateModule],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}
```

### Using the library — Standalone (Angular 19+)

Import `GridStateDirective` directly into a standalone component:

```typescript
import { GridStateDirective } from '@lucasheight/kendo-grid-state';

@Component({
  selector: 'app-my-grid',
  standalone: true,
  imports: [GridModule, GridStateDirective],
  templateUrl: './my-grid.component.html',
})
export class MyGridComponent {}
```

### Template

Add the directive to the grid and provide a unique storage key via `gridState`:

```html
<kendo-grid
  gridState="ANiceGrid"
  (stateReady)="onGotState($event)"
  [data]="data$ | async"
  [pageable]="{
    buttonCount: 5,
    info: true,
    type: 'numeric',
    pageSizes: true,
    previousNex: true
  }"
  [loading]="loading"
  [pageSize]="gridState.take"
  [filter]="gridState.filter"
  [groupable]="false"
  [group]="gridState.group"
  [sortable]="true"
  [skip]="gridState.skip"
  [sort]="gridState.sort"
  [filterable]="true"
  [resizable]="true"
  [reorderable]="true"
  [columnMenu]="true"
  (dataStateChange)="onStateChange($event)"
>
  <kendo-grid-column field="ProductName"></kendo-grid-column>
  <kendo-grid-column field="SupplierID" filter="numeric"></kendo-grid-column>
  <kendo-grid-column field="QuantityPerUnit"></kendo-grid-column>
</kendo-grid>
```

In the component handle the `stateReady` event:

```typescript
  loading: boolean = false;
  gridState: State = { skip: 0, take: 5 };
  data$: Observable<GridDataResult>;
  onGotState = (e: State): void => {
    this.onStateChange(e as DataStateChangeEvent);
  };
  public onStateChange = (e: DataStateChangeEvent): void => {
    this.loading = true;
    this.gridState = e;
    this.service.query(toODataString(e));
  };
```

## Changing Gridstate storage provider

To change the application storage for all grids in your application, add the APP_STORAGE provider:

For example, this sets the provider to use localStorage instead of the default sessionStorage.

```typescript
// NgModule approach
@NgModule({
  declarations: [AppComponent, GridDirectiveComponent],
  imports: [BrowserModule, BrowserAnimationsModule, CommonModule, HttpClientModule, GridModule, GridStateModule],
  providers: [{ provide: APP_STORAGE, useFactory: () => localStorage }],
  bootstrap: [AppComponent],
})
export class AppModule {}
```

```typescript
// Standalone approach
bootstrapApplication(AppComponent, {
  providers: [{ provide: APP_STORAGE, useFactory: () => localStorage }],
});
```

### Custom storage providers

To implement your own custom storage provider, implement the Storage interface. Then add your factory to the provider. E.g:

```typescript
export const CustomStorage: Storage = {
  length: undefined,
  clear(): void {
    throw new Error("Method not implemented.");
  },
  getItem(key: string): string {
    return "hello custom storage";
  },
  key(index: number): string {
    return "hello from custom storage";
  },
  removeItem(key: string): void {
    console.log("remove custom storage", key);
  },
  setItem(key: string, value: string): void {
    console.log("set custom storage", key);
  }
};
```

A demo can be found on [stackblitz here.](https://stackblitz.com/edit/angular-kendo-grid-state-directive)
