# Grid Structure

## Live example

{% hint style="success" %}
[Grid Structure](https://demos.dikesoft.com/dk-grid/grid-structure) live example.
{% endhint %}

## CSS Grid Layout

The DikeGrid uses the CSS Grid Layout specification to create its internal structure and display all the defined columns.&#x20;

As you know, the CSS Grid Layout specification uses column and row templates. That is why every part of the DikeGrid is called a row. Therefore, for instance, the Header is called the Header Row, the Content, Content Row, etc.

## Code for this section

You can read any sub-section in the order you want. However, we recommend reading all sub-sections as they appear.

The following initial configuration will increase in every sub-section.

{% tabs %}
{% tab title="grid-structure.component.html" %}

```markup
<dike-grid id="grid-structure"
    [width]="gridProperties.width"
    [height]="gridProperties.height"
    
    [displayRowId]="gridProperties.displayRowId"
    [gridElevation]="gridProperties.matElevation"
    [gridElevationValue]="gridProperties.elevationValue"
    [striped]="gridProperties.stripeRows"
    
    [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">
    </dike-grid-column>

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

{% endtab %}

{% tab title="grid-structure.component.ts" %}

```typescript
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';

import { Subscription } from 'rxjs';

import { DikeGridDataSourceInput } from '@dikesoft/data-grid';

import { Employee } from 'app/mock-api/common/employees/data.model';
import { DikeGridProperties } from 'app/core/config/dike-grid.properties';

import { DikeGridConfig } from 'app/services/dike-grid.config.service';
import { SampleData } from 'app/services/sample-data.service';

@Component({
  selector: 'grid-structure',
  templateUrl: './grid-structure.component.html',
  styleUrls: ['./grid-structure.component.scss'],

  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class GridStructureComponent implements OnInit, OnDestroy {

  dkgDataSource: DikeGridDataSourceInput<Employee>;
  gridProperties: DikeGridProperties;
  
  private changeGridPropertiesSubscription: Subscription = Subscription.EMPTY;

  constructor(
    private cdr: ChangeDetectorRef,
    private gridConfig: DikeGridConfig,
    private sampleData: SampleData) { }

  ngOnInit(): void {
    this.dkgDataSource = this.sampleData.getEmployees(1000);
    // Listening to any config property change:
    this.setChangeGridPropertiesSubscription();
  }

  ngOnDestroy(): void {
    this.changeGridPropertiesSubscription.unsubscribe();
  }

  private setChangeGridPropertiesSubscription(): void {
    this.changeGridPropertiesSubscription.unsubscribe();
    this.changeGridPropertiesSubscription = this.gridConfig.configChange.subscribe((props: DikeGridProperties) => {
      this.gridProperties = props;
      this.cdr.markForCheck();
    });
  }
}
```

{% endtab %}
{% endtabs %}

### Complete code

{% tabs %}
{% tab title="structure.module.ts" %}

```typescript
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';

import { DikeDataGridModule, DIVISION_PANEL_GAP,
    DIVISION_PANEL_LINE_WIDTH, BORDER_WIDTH, BORDER_GAP,
    COLUMN_CONTEXT_MENU_WIDTH, COLUMN_CONTEXT_MENU_HEIGHT,
    LOADING_MESSAGE
} from '@dikesoft/data-grid';

import { SharedModule } from 'app/shared/shared.module';
import { structureRoutes } from 'app/modules/admin/structure/structure.routing';
import { GridStructureComponent } from 'app/modules/admin/structure/grid-structure/grid-structure.component';

@NgModule({
  declarations: [
    GridStructureComponent
  ],
  imports: [
    CommonModule,
    RouterModule.forChild(structureRoutes),

    SharedModule,
    DikeDataGridModule
  ],
  providers: [
    { provide: DIVISION_PANEL_GAP, useValue: 21},
    { provide: DIVISION_PANEL_LINE_WIDTH, useValue: 3},
    { provide: BORDER_WIDTH, useValue: 3 },
    { provide: BORDER_GAP, useValue: 35 },
    { provide: COLUMN_CONTEXT_MENU_WIDTH, useValue: 700 },
    { provide: COLUMN_CONTEXT_MENU_HEIGHT, useValue: 550 },
    { provide: LOADING_MESSAGE, useValue: 'Loading rows of data, please wait...' }
  ]
})
export class StructureModule { }

```

{% endtab %}

{% tab title="grid-structure.component.html" %}

```markup
<div class="p-4 leading-6 text-secondary"><strong>Waiting Indicator message</strong></div>
<div class="p-4 flex flex-row flex-wrap justify-around items-center">
    <mat-form-field class="flex-auto w-80 mr-5">
        <mat-label>Custom message</mat-label>
        <input matInput
            type="text"
            [formControl]="customMessage">

        <mat-hint align="end">Text value</mat-hint>
        <mat-error *ngIf="customMessage.hasError('required')">Required</mat-error>
    </mat-form-field>
    <button mat-raised-button
        class="flex-none w-32 mr-5 mb-3"
        color="primary"
        [disabled]="!customMessage.valid"
        (click)="onDisplayWaitingIndicator()">Show Indicator
    </button>
    <button mat-raised-button
        class="flex-none w-32 mr-5 mb-3"
        color="primary"
        (click)="onHideWaitingIndicator()">Hide Indicator
    </button>
</div>

<dike-grid id="grid-structure" #grid="dkgGrid"
    [width]="gridProperties.width"
    [height]="gridProperties.height"

    [displayRowId]="gridProperties.displayRowId"
    [gridElevation]="gridProperties.matElevation"
    [gridElevationValue]="gridProperties.elevationValue"
    [striped]="gridProperties.stripeRows"
    [verticalRowLines]="gridProperties.verticalRowLines"
    
    [headerRowHeight]="gridProperties.headerHeight"
    [allowColumnContextMenu]="gridProperties.columnContextMenu"

    [allowRowFiltering]="gridProperties.allowRowFilter"
    [filterRowHeight]="gridProperties.filterRowHeight"

    [contentRowHeight]="gridProperties.contentRowHeight"

    allowRowGrouping
    [rowGroupingRowHeight]="gridProperties.rowGroupingHeight"
    [rowGroupingColumnHeight]="gridProperties.rowGroupingColumnHeight"
    [displayRowGroupingIndent]="gridProperties.displayRowGroupingIndent"
    [rowGroupingIndentWidth]="gridProperties.rowGroupingIndentWidth"

    allowSelection

    allowEdition
    [editionMode]="gridProperties.editionMode"
    [editionToolbar]="gridProperties.displayEditionToolbar"
    [editionToolbarPosition]="gridProperties.editionToolbarPosition"
    [editionToolbarAlignment]="gridProperties.editionToolbarAlignment"
    [editionToolbarRowHeight]="gridProperties.editionToolbarHeight"
    [editionToolbarItemHeight]="gridProperties.edtitionToolbarItemHeight"

    [allowPagination]="gridProperties.allowPagination"
    [paginationRowHeight]="gridProperties.paginationHeight"

    [allowColumnDragging]="gridProperties.allowColumnDragging"
    [datasource]="dkgDataSource">

    <dike-grid-column
        fieldName="employeeId"
        headerText="Employee Id"
        dataType="Text"
        width="350"
        panel="leftPanel"
        displayMenu="false">
    </dike-grid-column>

    <dike-grid-column
        fieldName="completeNameGroup"
        headerText="Complete Name">
        
        <dike-grid-column
            fieldName="firstName"
            headerText="Name"
            dataType="Text">
        </dike-grid-column>
    
        <dike-grid-column
            fieldName="lastName"
            headerText="Surname"
            dataType="Text">
        </dike-grid-column>
        
    </dike-grid-column>
    
    <dike-grid-column
        fieldName="gender"
        headerText="Gender"
        dataType="Binary"
        width="110"
        groupable
        draggable
        panel="groupPanel">
    </dike-grid-column>

    <dike-grid-column
        fieldName="age"
        headerText="Age"
        dataType="Numeric"
        contentAlign="center"
        width="85"
        groupable
        draggable
        panel="groupPanel">
    </dike-grid-column>

    <dike-grid-column
        fieldName="email"
        headerText="Email"
        dataType="Text"
        width="300">
    </dike-grid-column>

    <dike-grid-column
        fieldName="hireDate"
        headerText="Hire Date"
        dataType="Date"
        panel="rightPanel">
    </dike-grid-column>
</dike-grid>
```

{% endtab %}

{% tab title="grid-structure.component.ts" %}

```typescript
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
import { FormControl, Validators } from '@angular/forms';

import { Subscription } from 'rxjs';
import { delay } from 'rxjs/operators';

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

import { Employee } from 'app/mock-api/common/employees/data.model';
import { DikeGridProperties } from 'app/core/config/dike-grid.properties';

import { DikeGridConfig } from 'app/services/dike-grid.config.service';
import { SampleData } from 'app/services/sample-data.service';

@Component({
  selector: 'grid-structure',
  templateUrl: './grid-structure.component.html',
  styleUrls: ['./grid-structure.component.scss'],

  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class GridStructureComponent implements OnInit, OnDestroy {

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

  dkgDataSource: DikeGridDataSourceInput<Employee>;
  gridProperties: DikeGridProperties;
  customMessage: FormControl;

  private changeGridPropertiesSubscription: Subscription = Subscription.EMPTY;

  constructor(
    private cdr: ChangeDetectorRef,
    private gridConfig: DikeGridConfig,
    private sampleData: SampleData) {

    this.customMessage = new FormControl('', Validators.required);
  }

  ngOnInit(): void {
    this.dkgDataSource = this.sampleData.getEmployees(1000).pipe(delay(2000));
    // Listening to any config property change:
    this.setChangeGridPropertiesSubscription();
  }

  ngOnDestroy(): void {
    this.changeGridPropertiesSubscription.unsubscribe();
  }

  onDisplayWaitingIndicator(): void {
    this.dikeGrid.waitingIndicator.customMessageIndicator(this.customMessage.value as string);
  }

  onHideWaitingIndicator(): void {
    this.dikeGrid.waitingIndicator.hideWaitingIndicator();
  }

  private setChangeGridPropertiesSubscription(): void {
    this.changeGridPropertiesSubscription.unsubscribe();
    this.changeGridPropertiesSubscription = this.gridConfig.configChange.subscribe((props: DikeGridProperties) => {
      this.gridProperties = props;
      this.cdr.markForCheck();
    });
  }
}

```

{% endtab %}
{% endtabs %}
