Skip to content

Latest commit

 

History

History
 
 

grid

Zen Grid

<zen-grid> is a component that wraps Kendo Angular Grid and implements a data source adapter to interface with the code generated GraphQL module @zen/graphql. With minimal configuration, <zen-grid> will render a fully featured data grid over any Prisma model within the project. Intelligent default implementations for the varying Kendo grid features have all been implemented. By converting the Kendo Grid state object into valid Prisma queries that will be made via the code generated GraphQL API gateway, sophisticated queries over Prisma models can be simply designed utilizing Kendo Grid's robust filter UIs. The grid leverages Apollo InMemoryCache to ensure network request are only incurred when necessary. Also, the grid implements an efficient, scalable, server-side pagination strategy, giving you pagination for free.

Configuration is made simple by providing the GQL documents generated via @zen/graphql and listing them within the grid settings.

zen-user-grid.component.ts

this.settings = {
  typename: 'User',
  findManyGQL: findManyUserGQL,
  findManyCountGQL: findManyUserCountGQL,
  deleteOneGQL: deleteOneUserGQL,
  defaultSettings: DEFAULT_SETTINGS,
  ability: ability
};

zen-user-grid.component.html

<zen-grid
  [mode]="mode"
  [settings]="settings"
  [selection]="selection"
  (add)="addHandler()" 
  (edit)="editHandler($event)">
</zen-grid>

The grid provides end-to-end type safety for its configuration, from the Prisma data type to the client-side type that is generated from the grid's GraphQL query. Define the columns of the grid utilizing the property columnsConfig under KendoGridSettings<T>, where T is the type containing the fields on the Prisma object being selected for within the grid's GraphQL request. Sensibly, a column can only be added if its field exists within the GraphQL query made for the grid. For usage of <zen-grid>, view the <zen-user-grid> component as a template for a complete solution.

zen-user-grid.component.ts

import { Component, Input } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { MatDialogModule } from '@angular/material/dialog';
import { Ability } from '@casl/ability';
import { DeleteOneUserGQL, FindManyUserCountGQL, FindManyUserGQL, UserFields } from '@zen/graphql';
import { GridMode, KendoGridSettings, ZenGridComponent, ZenGridSettings } from '@zen/grid';

import { DialogData, ZenUserInputComponent } from '../zen-user-input';

const DEFAULT_SETTINGS: KendoGridSettings<UserFields> = {
  rowColorStyles: [
    {
      condition: row => row.roles.includes('Super'),
      hexColor: '#003333',
    },
  ],
  columnsConfig: [
    {
      field: 'id',
      title: 'ID',
      filter: 'text',
      hidden: true,
    },
    {
      field: 'username',
      title: 'Username',
      custom: {
        /** @comment set this to true when fields are nullable on the Prisma model */
        nullable: true,
      },
    },
    {
      field: 'email',
      title: 'Email',
    },
    {
      field: 'createdAt',
      title: 'Created At',
      filter: 'date',
    },
    {
      field: 'roles',
      title: 'Roles',
      filterable: false,
      sortable: false,
    },
  ],
};

@Component({
  selector: 'zen-user-grid',
  templateUrl: 'zen-user-grid.component.html',
  standalone: true,
  imports: [MatDialogModule, ZenGridComponent],
})
export class ZenUserGridComponent {
  @Input() mode = GridMode.Default;
  @Input() selection: Array<UserFields['id']> = [];
  settings: ZenGridSettings<UserFields>;

  constructor(
    findManyUserGQL: FindManyUserGQL,
    findManyUserCountGQL: FindManyUserCountGQL,
    deleteOneUserGQL: DeleteOneUserGQL,
    ability: Ability,
    private dialog: MatDialog
  ) {
    this.settings = {
      typename: 'User',
      findManyGQL: findManyUserGQL,
      findManyCountGQL: findManyUserCountGQL,
      deleteOneGQL: deleteOneUserGQL,
      defaultSettings: DEFAULT_SETTINGS,
      ability: ability,
    };
  }

  addHandler() {
    this.inputDialog({ action: 'create' });
  }

  editHandler({ dataItem }: { dataItem: UserFields }) {
    this.inputDialog({ action: 'edit', item: structuredClone(dataItem) });
  }

  inputDialog(data: DialogData) {
    this.dialog.open(ZenUserInputComponent, {
      data,
      disableClose: true,
    });
  }
}

Detail Row Template

The master details template row item can be accessed via zenGridDetailTemplate which imitates kendoGridDetailTemplate. For usage, please view the following code.

<zen-grid [settings]="settings">
  <ng-template zenGridDetailTemplate let-dataItem [zenGridDetailTemplateShowIf]="showDetails">
    id: {{dataItem.id}}
  </ng-template>
</zen-grid>