# Column Definitions

## Live example

{% hint style="success" %}
[Column Definitions](https://demos.dikesoft.com/dk-grid/column/definitions) live example.
{% endhint %}

## HTML definition

A column could be created in the HTML definition directly. Use the <mark style="color:red;">`dike-grid-column`</mark> selector just beneath the <mark style="color:red;">`dike-grid`</mark> selector.

In the following example three columns were defined using the [<mark style="color:green;">`DikeGridColumnComponent`</mark>](https://docs.dikesoft.com/reference/components/dkgridcolumncomponent#component-metadata) selector:

{% code title="column-definitions.component.html" %}

```markup
<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>
```

{% endcode %}

As it was mentioned in the [Quick Start Tutorial](https://docs.dikesoft.com/getting-started/quick-start-tutorial#column-definitions), the minimum number of properties to define a column are `fieldName`, `headerText` and `dataType`.

{% hint style="info" %}
For a complete list of column properties, see the [<mark style="color:green;">`DikeGridColumnComponent`</mark>](https://docs.dikesoft.com/reference/components/dkgridcolumncomponent#properties) definition.
{% endhint %}

## 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 <mark style="color:green;">`DikeGridColumnDef`</mark> from the <mark style="color:green;">`DikeGridComponent`</mark> instance you are defining columns.

There are two ways of grabbing this instance:

#### Querying the <mark style="color:green;">`DikeGridComponent`</mark> from the View

Every <mark style="color:green;">`DikeGridComponent`</mark> instance has its own <mark style="color:green;">`DikeGridColumnDef`</mark> instance. The instance is exposed as a public property called <mark style="color:orange;">`columnDef`</mark>.

{% hint style="info" %}
See the [<mark style="color:green;">`DikeGridComponent`</mark>](https://docs.dikesoft.com/reference/components/dkgridcomponent) definition for a complete list of properties.
{% endhint %}

The following code snippet shows how the <mark style="color:green;">`DikeGridComponent`</mark> is retrieved and then, how **Gender** and **Age** columns are added using the column API.

{% tabs %}
{% tab title="column-definitions.component.html" %}

```markup
<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>
```

{% endtab %}

{% tab title="column-definitions.component.ts" %}

```typescript
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 ]);
    });
  }
}

```

{% endtab %}
{% endtabs %}

{% hint style="success" %}
**Mixed Column Definition**. Notice how three columns are defined in the HTML and the others are defined in code.
{% endhint %}

#### Retrieving the <mark style="color:green;">`DikeGridColumnDef`</mark> instance

The <mark style="color:green;">`DikeGridColumnDef`</mark> instance could be retrieved listening to the event called <mark style="color:orange;">`gridColumnDefInstance`</mark> from the <mark style="color:green;">`DikeGridComponent`</mark>.

{% tabs %}
{% tab title="column-definitions.component.html" %}

```markup
<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>
```

{% endtab %}

{% tab title="column-definitions.component.ts" %}

```typescript
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 ]);
    });
  }
}
```

{% endtab %}
{% endtabs %}

As you can see in the previous code snippet, the <mark style="color:orange;">`gridColumnDefInstance`</mark> is attached to the `onColumnDefInstance()` method. In the method definition, two more columns were added: **Email** and **Hire Date**.

{% hint style="info" %}
The <mark style="color:orange;">`gridColumnDefInstance`</mark> event is emitted after the `ngOnInit()` lifecycle hook of the <mark style="color:green;">`DikeGridComponent`</mark> component.
{% endhint %}

The following screenshot shows the output after adding the columns:

![Defining columns](https://3888584995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpDxfe6pgRLqBLMQgZ0kG%2Fuploads%2FJjeRdiFeM836Mwd5datk%2Fcolum-definitions-adding-columns.png?alt=media\&token=8270a2c4-a1ae-43c0-b1ee-dc6daebe8f0f)

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.

{% hint style="success" %}
See the [Column Context Menu](https://docs.dikesoft.com/fundamentals/grid-structure/column-context-menu#suppress-the-column-context-menu) section for details.
{% endhint %}

## 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                                                                     |                                                                                                                                                                   |
| ------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <mark style="color:orange;">`gridColumnDefInstance`</mark> event listener             | As it was told, this event is emitted after the `ngOnInit()` lifecycle hook of the <mark style="color:green;">`DikeGridComponent`</mark> component.               |
| HTML definition                                                                       | These columns are added in the `ngAfterContentInit()` lifecycle hook of the <mark style="color:green;">`DikeGridComponent`</mark> component.                      |
| <mark style="color:green;">`DikeGridComponent`</mark> instance queried from the view. | These columns are added in the `ngAfterViewInit()` lifecycle hook of the component that has the <mark style="color:green;">`DikeGridComponent`</mark> definition. |

{% hint style="info" %}
In every **Column Definition** execution, the columns are added in the order they are defined unless the order property is set.
{% endhint %}

### Specifying the order of the columns

Let's say we want the following order:&#x20;

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:

![Setting the order of the columns](https://3888584995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpDxfe6pgRLqBLMQgZ0kG%2Fuploads%2F1ASJ2WKn4yK8mz9SRIA6%2Fcolum-definitions-columns-order.png?alt=media\&token=3d85dd01-bb98-421b-a95b-4cf98be0f5dc)

## Column types

Th DikeGrid Library defines four column types through a union type called <mark style="color:green;">`DikeColumnDataType`</mark>.

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`             | <p>It holds data of type <mark style="color:green;"><code>string</code></mark>.<br>Default alignment <mark style="color:red;"><code>start</code></mark>.</p>                                                                                                                 | Instance of type <mark style="color:green;">`DikeTextColumnDef`</mark>.    |
| `Numeric`          | <p>It holds data of type <mark style="color:green;"><code>number</code></mark>.<br>Default alignment <mark style="color:red;"><code>end</code></mark>.</p>                                                                                                                   | Instance of type <mark style="color:green;">`DikeNumericColumnDef`</mark>. |
| `Date`             | <p>It hold data of type <mark style="color:green;"><code>string</code></mark>, <mark style="color:green;"><code>number</code></mark>, <mark style="color:green;"><code>Date</code></mark>.<br>Default alignment <mark style="color:red;"><code>center</code></mark>.</p>     | Instance of type <mark style="color:green;">`DikeDateColumnDef`</mark>.    |
| `Binary`           | <p>It holds data of type <mark style="color:green;"><code>string</code></mark>, <mark style="color:green;"><code>number</code></mark>, <mark style="color:green;"><code>boolean</code></mark>.<br>Default alignment <mark style="color:red;"><code>center</code></mark>.</p> | Instance of type <mark style="color:green;">`DikeBinaryColumnDef`</mark>.  |

{% hint style="info" %}
Content alignment comes from a union type called <mark style="color:green;">`ColumnAlignment`</mark>. This alignment could be set overwriting the default value.
{% endhint %}

When a column is defined via templating, the type must be provided through the <mark style="color:orange;">`dataType`</mark> 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:

```typescript
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:

```typescript
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 <mark style="color:green;">`GetterFn<T, R>`</mark> and <mark style="color:green;">`SetterFn<T, R>`</mark> 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 <mark style="color:green;">`Employee`</mark> interface to retrieve the sales for March month.

```typescript
// 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:

![Defining the getter function for the March Sales column](https://3888584995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpDxfe6pgRLqBLMQgZ0kG%2Fuploads%2FEtVQgET4OyuIQokFV7Ks%2Fcolum-definitions-getterFn.png?alt=media\&token=68373e0d-ec7c-436e-a600-0fc2ab5c7aa6)

As you can see, the `marchSales` field was defined but it does not exist. There is no `marchSales` field in the <mark style="color:green;">`Employee`</mark> 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:

```typescript
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

```markup
<!-- 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

```markup
<!-- 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>
```

{% hint style="info" %}
To see more on [Angular pipes](https://angular.io/guide/pipes) visit the official docs.
{% endhint %}

### 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.

{% code title="column-definitions.component.html" %}

```markup
<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>
```

{% endcode %}

Both templates are assigned to the input property called <mark style="color:orange;">`displayTemplate`</mark>.

#### Gender template

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

{% tabs %}
{% tab title="column-definitions.component.html" %}

```markup
<!-- 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>
```

{% endtab %}

{% tab title="column-definitions.component.ts" %}

```typescript
@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 ]);
    });
  }
}
```

{% endtab %}
{% endtabs %}

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:

{% tabs %}
{% tab title="column-definitions.component.html" %}

```markup
<!-- 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>
```

{% endtab %}

{% tab title="column-definitions.component.ts" %}

```typescript
@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 ]);
  }
}
```

{% endtab %}
{% endtabs %}

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 <mark style="color:orange;">`displayTemplate`</mark> column property because both columns are defined in the <mark style="color:orange;">`gridColumnDefInstance`</mark> event callback. Column templates will be available until the `ngAfterViewInit` hook and, remember that the <mark style="color:orange;">`gridColumnDefInstance`</mark> event is emitted just after the **DikeGridComponent's** `ngOnInit` hook.

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

![Custom column templates](https://3888584995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpDxfe6pgRLqBLMQgZ0kG%2Fuploads%2FnqiS5LrVQ2eE6ioeV91p%2Fcolum-definitions-custom-templates.png?alt=media\&token=27c3f8da-c44a-4e17-a3b8-b3917d5204ce)

## 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 <mark style="color:orange;">`columnId`</mark>, <mark style="color:orange;">`slotId`</mark> and <mark style="color:orange;">`belongToGroup`</mark> properties.

## Summary

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

### Complete code for this section

{% tabs %}
{% tab title="column-definitions.component.html" %}

```markup
<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>
```

{% endtab %}

{% tab title="column-definitions.component.ts" %}

```typescript
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 ]);
    });
  }
}
```

{% endtab %}
{% endtabs %}
