DkGrid
  • Overview
  • Getting Started
    • Quick Start Tutorial
  • Fundamentals
    • Grid Structure
      • Grid Size
      • Header
      • Row Filter
      • Rows
      • Panels
      • Gutters
      • Edition Toolbar
      • Paginator
      • Borders
      • Column Context Menu
      • Waiting Indicator
    • DataSource
      • In-Memory DataSource
      • Custom DataSource
    • Theming
  • Columns
    • Column Definitions
    • Column Grouping
    • Column Sizing
    • Column Moving
    • Column Pinning
  • Rows
    • Row Sorting
    • Row Selection
    • Row Grouping
    • Row Pagination
  • Filtering
    • Column Filters
    • Filter types
    • In-line Filters
  • Editing
    • Row Edition
    • Edition templates
    • Edition validation
    • Multiple rows edition
  • Reference
    • DkGrid API
      • DkGridColumnDef
      • DkGridSorting
      • DkGridSelection
      • DkGridRowGrouping
      • DkGridPagination
      • DkGridWaitingIndicator
      • DkGridFactoryDataSource
      • DkGridFilter
      • DkGridEdition
    • Components
      • DkGridComponent
      • DkGridColumnComponent
    • Classes
      • DataSource
      • Columns
      • Rows
      • Filtering
      • Editing
    • Interfaces
      • Columns
      • Sorting
      • Row Grouping
      • Filtering
      • Editing
    • Injection Tokens
      • Grid Structure
      • Filtering
      • Editing
      • Theming
    • Type aliases
      • DataSource
      • Columns
      • Selection
      • Filtering
      • Editing
    • Type Guards
Powered by GitBook
On this page
  • Live example
  • HTML definition
  • TypeScript code definition
  • DikeGrid Column API
  • Columns Order
  • Specifying the order of the columns
  • Column types
  • Retrieving and Updating a field value
  • Templates for displaying field values
  • Text and Binary columns
  • Numeric and Date columns
  • Custom templates
  • Column Identifiers
  • Summary
  • Complete code for this section
  1. Columns

Column Definitions

This section describes how to create columns in the component's HTML definition or in the TypeScript class file.

PreviousThemingNextColumn Grouping

Last updated 2 years ago

Live example

live example.

HTML definition

A column could be created in the HTML definition directly. Use the dike-grid-column selector just beneath the dike-grid selector.

In the following example three columns were defined using the selector:

column-definitions.component.html
<dike-grid #grid="dkgGrid" id="grid-col-def" height="500px"
    [datasource]="dkgDataSource">

    <dike-grid-column
        fieldName="employeeId"
        headerText="Employee Id"
        dataType="Text"
        width="350">
    </dike-grid-column>
    
    <dike-grid-column
        fieldName="firstName"
        headerText="Name"
        dataType="Text"
        width="150">
    </dike-grid-column>
    
    <dike-grid-column
        fieldName="lastName"
        headerText="Surname"
        dataType="Text"
        width="150">
    </dike-grid-column>

</dike-grid>

TypeScript code definition

It is also possible to define a column in the TypeScript's component file.

DikeGrid Column API

In order to define a column in the TypeScript's component file, you must grab the corresponding column API of type DikeGridColumnDef from the DikeGridComponent instance you are defining columns.

There are two ways of grabbing this instance:

Querying the DikeGridComponent from the View

Every DikeGridComponent instance has its own DikeGridColumnDef instance. The instance is exposed as a public property called columnDef.

The following code snippet shows how the DikeGridComponent is retrieved and then, how Gender and Age columns are added using the column API.

<dike-grid #grid="dkgGrid" id="grid-col-def" height="500px"
    gridElevation
    striped
    [datasource]="dkgDataSource">

    <dike-grid-column
        fieldName="employeeId"
        headerText="Employee Id"
        dataType="Text"
        width="350"
        sortable>
    </dike-grid-column>

    <dike-grid-column
        fieldName="firstName"
        headerText="Name"
        dataType="Text"
        width="150"
        sortable>
    </dike-grid-column>

    <dike-grid-column
        fieldName="lastName"
        headerText="Surname"
        dataType="Text"
        width="150">
    </dike-grid-column>

</dike-grid>
import { AfterViewInit, Component, OnInit, ViewChild, ViewEncapsulation, ChangeDetectionStrategy } from '@angular/core';

import { DikeGridComponent, DikeGridDataSourceInput, 
  DikeBinaryColumnDef, DikeNumericColumnDef 
} from '@dikesoft/angular-data-grid';

import { Employee } from 'app/mock-api/common/employees/data.model';
import { SampleData } from 'app/services/sample-data.service';

@Component({
  selector: 'column-definitions',
  templateUrl: './column-definitions.component.html',
  styleUrls: ['./column-definitions.component.scss'],
  
  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ColumnDefinitionsComponent implements OnInit, AfterViewInit {
  // Retrieve the DikeGridComponent<T> instance from the view:
  @ViewChild('grid') dikeGrid: DikeGridComponent<Employee>;

  dkgDataSource: DikeGridDataSourceInput<Employee>;

  constructor(
    private sampleData: SampleData) { }

  ngOnInit(): void {
    this.dkgDataSource = this.sampleData.getEmployees(1000);
  }

  ngAfterViewInit(): void {
    // The DikeGridComponent<T> instance is available:
    Promise.resolve().then(() => {
      // Define the Gender column:
      const genderColumn = new DikeBinaryColumnDef<Employee>('gender', 'Gender');
      genderColumn.width = 110;

      // Define the Age column:
      const ageColumn = new DikeNumericColumnDef<Employee>('age', 'Age');
      ageColumn.width = 85;

      // Finally, add them to the DikeGridComponent<T> instance:
      this.dikeGrid.columnDef.addColumns([ genderColumn, ageColumn ]);
    });
  }
}

Mixed Column Definition. Notice how three columns are defined in the HTML and the others are defined in code.

Retrieving the DikeGridColumnDef instance

The DikeGridColumnDef instance could be retrieved listening to the event called gridColumnDefInstance from the DikeGridComponent.

<dike-grid #grid="dkgGrid" id="grid-col-def" height="500px"
    gridElevation
    striped
    (gridColumnDefInstance)="onColumnDefInstance($event)"
    [datasource]="dkgDataSource">

    <dike-grid-column
        fieldName="employeeId"
        headerText="Employee Id"
        dataType="Text"
        width="350"
        sortable>
    </dike-grid-column>

    <dike-grid-column
        fieldName="firstName"
        headerText="Name"
        dataType="Text"
        width="150"
        sortable>
    </dike-grid-column>

    <dike-grid-column
        fieldName="lastName"
        headerText="Surname"
        dataType="Text"
        width="150">
    </dike-grid-column>

</dike-grid>
import { AfterViewInit, Component, OnInit, ViewChild, ViewEncapsulation, ChangeDetectionStrategy } from '@angular/core';

import { DikeGridComponent, DikeGridDataSourceInput, DikeBinaryColumnDef,
    DikeNumericColumnDef, DikeGridColumnDef, DikeTextColumnDef, DikeDateColumnDef
} from '@dikesoft/angular-data-grid';

import { Employee } from 'app/mock-api/common/employees/data.model';
import { SampleData } from 'app/services/sample-data.service';

@Component({
  selector: 'column-definitions',
  templateUrl: './column-definitions.component.html',
  styleUrls: ['./column-definitions.component.scss'],
  
  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ColumnDefinitionsComponent implements OnInit, AfterViewInit {

  // Retrieve the DikeGridComponent<T> instance from the view:
  @ViewChild('grid') dikeGrid: DikeGridComponent<Employee>;

  dkgDataSource: DikeGridDataSourceInput<Employee>;

  constructor(
    private sampleData: SampleData) { }

  onColumnDefInstance(columnDef: DikeGridColumnDef<Employee>): void {
    // Define the Email column:
    const emailColumn = new DikeTextColumnDef<Employee>('email', 'Email');
    emailColumn.width = 300;

    // Define the Hire Date column:
    const hireDateColumn = new DikeDateColumnDef<Employee>('hireDate', 'Hire Date');

    // Then, add the colums to the DikeGridComponent instance:
    columnDef.addColumns([ emailColumn, hireDateColumn ]);
  }

  ngOnInit(): void {
    this.dkgDataSource = this.sampleData.getEmployees(1000);
  }

  ngAfterViewInit(): void {
    // The DikeGridComponent<T> instance is available:
    Promise.resolve().then(() => {

      // Define the Gender column:
      const genderColumn = new DikeBinaryColumnDef<Employee>('gender', 'Gender');
      genderColumn.width = 110;

      // Define the Age column:
      const ageColumn = new DikeNumericColumnDef<Employee>('age', 'Age');
      ageColumn.width = 85;

      // Finally, add them to the DikeGridComponent<T> instance:
      this.dikeGrid.columnDef.addColumns([ genderColumn, ageColumn ]);
    });
  }
}

As you can see in the previous code snippet, the gridColumnDefInstance is attached to the onColumnDefInstance() method. In the method definition, two more columns were added: Email and Hire Date.

The gridColumnDefInstance event is emitted after the ngOnInit() lifecycle hook of the DikeGridComponent component.

The following screenshot shows the output after adding the columns:

By default, columns show a context menu. You can suppress this context menu for a specific column, all columns in a DikeGrid definition, or all DikeGrid instances.

Columns Order

Every column definition has an order property. If this property is not specified, the order of the columns depends on at which moment the columns are defined.

The following table shows the execution order the column definitions take place:

Column Definition

gridColumnDefInstance event listener

As it was told, this event is emitted after the ngOnInit() lifecycle hook of the DikeGridComponent component.

HTML definition

These columns are added in the ngAfterContentInit() lifecycle hook of the DikeGridComponent component.

DikeGridComponent instance queried from the view.

These columns are added in the ngAfterViewInit() lifecycle hook of the component that has the DikeGridComponent definition.

In every Column Definition execution, the columns are added in the order they are defined unless the order property is set.

Specifying the order of the columns

Let's say we want the following order:

  1. Employee Id

  2. Surname

  3. Name

  4. Gender

  5. Age

  6. Email

  7. Hire Date

After setting the order property, the output will be the following:

Column types

Th DikeGrid Library defines four column types through a union type called DikeColumnDataType.

Depending on which type the column is, there is a default alignment used to display the content of the rows.

DikeColumnDataType
Inner Type / Default alignment
Class Definition

Text

It holds data of type string. Default alignment start.

Instance of type DikeTextColumnDef.

Numeric

It holds data of type number. Default alignment end.

Instance of type DikeNumericColumnDef.

Date

It hold data of type string, number, Date. Default alignment center.

Instance of type DikeDateColumnDef.

Binary

It holds data of type string, number, boolean. Default alignment center.

Instance of type DikeBinaryColumnDef.

Content alignment comes from a union type called ColumnAlignment. This alignment could be set overwriting the default value.

When a column is defined via templating, the type must be provided through the dataType input property. If the column is defined in code, the corresponding class instance must be created.

Retrieving and Updating a field value

By default, every column defines functions for getting or setting its field value. For instance, consider a Numeric column, its default getter function is:

getValue: GetterFn<T, number> = (entry: T): number => {
  return ((entry as { [key in keyof T]: T[key] })[this.fieldName]) as number;
};

And its default setter function is:

setValue: SetterFn<T, number> = (entry: T, value: number): void => {
  (entry as { [key in keyof T]: T[key] })[this.fieldName] = value;
 };

These functions are of type GetterFn<T, R> and SetterFn<T, R> respectively. These default functions treat the received object of type T as a simple object, which means an object without any nested object.

Let's define the getter function for the Employee interface to retrieve the sales for March month.

// Define the March Sales column:
const marchSales = new DikeNumericColumnDef<Employee>('marchSales', 'March Sales');
marchSales.width = 150;
marchSales.getValue = (entry: Employee): number => entry.sales.monthlySales['March'];

The result of adding the column March Sales is shown in the following image:

As you can see, the marchSales field was defined but it does not exist. There is no marchSales field in the Employee interface, the value is in a nested object. Therefore, it is mandatory to define the getter function that retrieves the desired value.

If the column were editable, the corresponding setter function looks like the following:

marchSales.setValue = (entry: Employee, value: number): void => {
    entry.sales.monthlySales['March'] = value;
};

Templates for displaying field values

Every column has a default template for displaying its field value. This template depends on the column type because depending on the type the corresponding Angular Pipe is applied.

Text and Binary columns

<!-- Template definition for Text columns -->
<ng-template #dikeTextDisplay let-entry="rowEntry" let-value="fieldValue">
  <p>{{ value }}</p>
</ng-template>

<!-- Template definition for Binary columns -->
<ng-template #dikeBinaryDisplay let-entry="rowEntry" let-value="fieldValue">
  <p>{{ value }}</p>
</ng-template>

As you can see, for Text and Binary columns no Angular Pipes are applied.

Numeric and Date columns

<!-- Template definition for Numeric columns -->
<ng-template #dikeNumericDisplay let-entry="rowEntry" let-value="fieldValue">
  <p>{{ value | number }}</p>
</ng-template>

<!-- Template definition for Date columns -->
<ng-template #dikeDateDisplay let-entry="rowEntry" let-value="fieldValue">
  <p>{{ value | date:'shortDate' }}</p>
</ng-template>

Custom templates

You can define your own templates. If you notice when defining a template you always have available the row entry and the field value. Let's define custom templates for Surname, Name, Gender, Hire Date, and March Sales.

Surname and Name templates

The uppercase Angular Pipe for Surname and Name column templates was added. These templates are bound in the HTML definition.

column-definitions.component.html
<dike-grid-column
    fieldName="firstName"
    headerText="Name"
    dataType="Text"
    width="150"
    order="2"
    [displayTemplate]="firstName">

    <ng-template #firstName let-value="fieldValue">
        <p>{{ value | uppercase }}</p>
    </ng-template>
</dike-grid-column>

<dike-grid-column
    fieldName="lastName"
    headerText="Surname"
    dataType="Text"
    width="150"
    order="1"
    [displayTemplate]="lastName">

    <ng-template #lastName let-value="fieldValue">
        <p>{{ value | uppercase }}</p>
    </ng-template>
</dike-grid-column>

Both templates are assigned to the input property called displayTemplate.

Gender template

See the following code snippet for the Gender column template definition:

<!-- Gender column template is defined outside the dike-grid selector -->
<ng-template #gender let-value="fieldValue">
    <mat-icon [matTooltip]="value">{{ value }}</mat-icon>
</ng-template>
@Component({
  selector: 'column-definitions',
  templateUrl: './column-definitions.component.html',
  styleUrls: ['./column-definitions.component.scss'],
  
  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ColumnDefinitionsComponent implements OnInit, AfterViewInit {
  // Retrieve the corresponding template:
  @ViewChild('gender', { read: TemplateRef }) genderTpl: TemplateRef<any>;

  constructor(
    private sampleData: SampleData) { }

  ngAfterViewInit(): void {
    // The DikeGridComponent<T> instance is available:
    Promise.resolve().then(() => {

      // Define the Gender column:
      const genderColumn = new DikeBinaryColumnDef<Employee>('gender', 'Gender');
      genderColumn.width = 110;
      genderColumn.order = 4;
      // Since genderTpl is available in this life cycle hook, just assign the template:
      genderColumn.displayTemplate = this.genderTpl;

      // Define the Age column:
      const ageColumn = new DikeNumericColumnDef<Employee>('age', 'Age');
      ageColumn.width = 85;
      ageColumn.order = 5;

      // Finally, add them to the DikeGridComponent<T> instance:
      this.dikeGrid.columnDef.addColumns([ genderColumn, ageColumn ]);
    });
  }
}

As you can see the Gender column template is retrieved querying the component's view. Remember that queried elements are set before the ngAfterViewInit life cycle hook, and the Gender column is defined in the ngAfterViewInit life cycle hook, the Gender column template is assigned to its corresponding column property.

Hire Date and March Sales column templates

In the following code snippet is shown the column templates definitions:

<!-- Column templates are defined outside the dike-grid selector -->
<ng-template #hireDate let-value="fieldValue">
    <p>{{ value | date:'fullDate' }}</p>
</ng-template>

<ng-template #marchSales let-value="fieldValue">
    <p>{{ value | currency }}</p>
</ng-template>
@Component({
  selector: 'column-definitions',
  templateUrl: './column-definitions.component.html',
  styleUrls: ['./column-definitions.component.scss'],
  
  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ColumnDefinitionsComponent implements OnInit, AfterViewInit {
  // Retrieve the corresponding template:
  @ViewChild('hireDate', { read: TemplateRef }) hireDateTpl: TemplateRef<any>;
  @ViewChild('marchSales', { read: TemplateRef }) marchSalesTpl: TemplateRef<any>;
  
  constructor(
    private sampleData: SampleData) { }

  onColumnDefInstance(columnDef: DikeGridColumnDef<Employee>): void {
    // Define the Email column:
    const emailColumn = new DikeTextColumnDef<Employee>('email', 'Email');
    emailColumn.width = 300;
    emailColumn.order = 6;

    // Define the Hire Date column:
    const hireDateColumn = new DikeDateColumnDef<Employee>('hireDate', 'Hire Date');
    hireDateColumn.order = 7;
    hireDateColumn.width = 215;
    hireDateColumn.displayTemplate = from(Promise.resolve().then(() => this.hireDateTpl));

    // Define the March Sales column:
    const marchSales = new DikeNumericColumnDef<Employee>('marchSales', 'March Sales');
    marchSales.order = 8;
    marchSales.width = 150;
    marchSales.getValue = (entry: Employee): number => entry.sales.monthlySales['March'];
    /**
     * Since Hire Date and March Sales columns are defined before the templates are ready
     * and available, an Observable is assigned waiting for the template availability.
     */
    marchSales.displayTemplate = from(Promise.resolve().then(() => this.marchSalesTpl));

    // Then, add the colums to the DikeGridComponent instance:
    columnDef.addColumns([ emailColumn, hireDateColumn, marchSales ]);
  }
}

For Hire Date and March Sales column templates, the date and currency Angular Pipes are used respectively.

For these columns, an Observable is assigned to displayTemplate column property because both columns are defined in the gridColumnDefInstance event callback. Column templates will be available until the ngAfterViewInit hook and, remember that the gridColumnDefInstance event is emitted just after the DikeGridComponent's ngOnInit hook.

The following screenshot shows the output after defining the custom templates.

Column Identifiers

All column identifiers are UUIDs and are used internally. If the user assigns them when defining columns, these are ignored.

The column identifiers are columnId, slotId and belongToGroup properties.

Summary

In this section, the main building blocks were covered. Columns are the main part for displaying data through a DikeGrid instance.

Complete code for this section

<dike-grid #grid="dkgGrid" id="grid-col-def" height="500px"
    gridElevation
    striped
    (gridColumnDefInstance)="onColumnDefInstance($event)"
    [datasource]="dkgDataSource">

    <dike-grid-column
        fieldName="employeeId"
        headerText="Employee Id"
        dataType="Text"
        width="350"
        order="0">
    </dike-grid-column>

    <dike-grid-column
        fieldName="firstName"
        headerText="Name"
        dataType="Text"
        width="150"
        order="2"
        [displayTemplate]="firstName">

        <ng-template #firstName let-value="fieldValue">
            <p>{{ value | uppercase }}</p>
        </ng-template>
    </dike-grid-column>

    <dike-grid-column
        fieldName="lastName"
        headerText="Surname"
        dataType="Text"
        width="150"
        order="1"
        [displayTemplate]="lastName">

        <ng-template #lastName let-value="fieldValue">
            <p>{{ value | uppercase }}</p>
        </ng-template>
    </dike-grid-column>

</dike-grid>

<ng-template #gender let-value="fieldValue">
    <mat-icon [matTooltip]="value">{{ value }}</mat-icon>
</ng-template>

<ng-template #hireDate let-value="fieldValue">
    <p>{{ value | date:'fullDate' }}</p>
</ng-template>

<ng-template #marchSales let-value="fieldValue">
    <p>{{ value | currency }}</p>
</ng-template>
import { AfterViewInit, Component, OnInit, ViewChild, TemplateRef, ViewEncapsulation, ChangeDetectionStrategy } from '@angular/core';
import { from } from 'rxjs';

import { DikeGridComponent, DikeGridDataSourceInput, DikeBinaryColumnDef,
    DikeNumericColumnDef, DikeGridColumnDef, DikeTextColumnDef, DikeDateColumnDef
} from '@dikesoft/angular-data-grid';

import { Employee } from 'app/mock-api/common/employees/data.model';
import { SampleData } from 'app/services/sample-data.service';

@Component({
  selector: 'column-definitions',
  templateUrl: './column-definitions.component.html',
  styleUrls: ['./column-definitions.component.scss'],
  
  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ColumnDefinitionsComponent implements OnInit, AfterViewInit {

  // Retrieve the DikeGridComponent<T> instance from the view:
  @ViewChild('grid') dikeGrid: DikeGridComponent<Employee>;
  // Retrieve the corresponding template:
  @ViewChild('gender', { read: TemplateRef }) genderTpl: TemplateRef<any>;
  @ViewChild('hireDate', { read: TemplateRef }) hireDateTpl: TemplateRef<any>;
  @ViewChild('marchSales', { read: TemplateRef }) marchSalesTpl: TemplateRef<any>;

  dkgDataSource: DikeGridDataSourceInput<Employee>;

  constructor(
    private sampleData: SampleData) { }

  onColumnDefInstance(columnDef: DikeGridColumnDef<Employee>): void {
    // Define the Email column:
    const emailColumn = new DikeTextColumnDef<Employee>('email', 'Email');
    emailColumn.width = 300;
    emailColumn.order = 6;

    // Define the Hire Date column:
    const hireDateColumn = new DikeDateColumnDef<Employee>('hireDate', 'Hire Date');
    hireDateColumn.order = 7;
    hireDateColumn.width = 215;
    hireDateColumn.displayTemplate = from(Promise.resolve().then(() => this.hireDateTpl));

    // Define the March Sales column:
    const marchSales = new DikeNumericColumnDef<Employee>('marchSales', 'March Sales');
    marchSales.order = 8;
    marchSales.width = 150;
    marchSales.getValue = (entry: Employee): number => entry.sales.monthlySales['March'];
    /**
     * Since Hire Date and March Sales columns are defined before the templates are ready
     * and available, an Observable is assigned waiting for the template availability.
     */
    marchSales.displayTemplate = from(Promise.resolve().then(() => this.marchSalesTpl));

    // Then, add the colums to the DikeGridComponent instance:
    columnDef.addColumns([ emailColumn, hireDateColumn, marchSales ]);
  }

  ngOnInit(): void {
    this.dkgDataSource = this.sampleData.getEmployees(1000);
  }

  ngAfterViewInit(): void {
    // The DikeGridComponent<T> instance is available:
    Promise.resolve().then(() => {

      // Define the Gender column:
      const genderColumn = new DikeBinaryColumnDef<Employee>('gender', 'Gender');
      genderColumn.width = 110;
      genderColumn.order = 4;
      // Since genderTpl is available in this life cycle hook, just assign the template:
      genderColumn.displayTemplate = this.genderTpl;

      // Define the Age column:
      const ageColumn = new DikeNumericColumnDef<Employee>('age', 'Age');
      ageColumn.width = 85;
      ageColumn.order = 5;

      // Finally, add them to the DikeGridComponent<T> instance:
      this.dikeGrid.columnDef.addColumns([ genderColumn, ageColumn ]);
    });
  }
}

As it was mentioned in the , the minimum number of properties to define a column are fieldName, headerText and dataType.

For a complete list of column properties, see the definition.

See the definition for a complete list of properties.

See the section for details.

To see more on visit the official docs.

DikeGridComponent
Angular pipes
Column Definitions
DikeGridColumnComponent
DikeGridColumnComponent
Column Context Menu
Quick Start Tutorial
Defining columns
Setting the order of the columns
Defining the getter function for the March Sales column
Custom column templates