From 2d816daa03a48aea87c0fbf30c02ad8882904145 Mon Sep 17 00:00:00 2001
From: Vildan Softic <zewa666@gmail.com>
Date: Tue, 19 Dec 2023 21:00:38 +0100
Subject: [PATCH] feat: add example for custom header and footer

---
 src/app/app-routing.module.ts                 |  2 +
 src/app/app.component.html                    |  5 ++
 src/app/app.module.ts                         |  5 +-
 .../grid-header-footer.component.html         | 30 ++++++++
 .../examples/grid-header-footer.component.ts  | 76 +++++++++++++++++++
 5 files changed, 117 insertions(+), 1 deletion(-)
 create mode 100644 src/app/examples/grid-header-footer.component.html
 create mode 100644 src/app/examples/grid-header-footer.component.ts

diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
index 4fff49390..c59d2d2f7 100644
--- a/src/app/app-routing.module.ts
+++ b/src/app/app-routing.module.ts
@@ -32,6 +32,7 @@ import { GridTradingComponent } from './examples/grid-trading.component';
 import { GridTreeDataHierarchicalComponent } from './examples/grid-tree-data-hierarchical.component';
 import { GridTreeDataParentChildComponent } from './examples/grid-tree-data-parent-child.component';
 import { SwtCommonGridTestComponent } from './examples/swt-common-grid-test.component';
+import { GridHeaderFooterComponent } from './examples/grid-header-footer.component';
 
 import { NgModule } from '@angular/core';
 import { Routes, RouterModule } from '@angular/router';
@@ -72,6 +73,7 @@ const routes: Routes = [
   { path: 'tree-data-parent-child', component: GridTreeDataParentChildComponent },
   { path: 'tree-data-hierarchical', component: GridTreeDataHierarchicalComponent },
   { path: 'swt', component: SwtCommonGridTestComponent },
+  { path: 'header-footer', component: GridHeaderFooterComponent },
   { path: '', redirectTo: '/trading', pathMatch: 'full' },
   { path: '**', redirectTo: '/trading', pathMatch: 'full' }
 ];
diff --git a/src/app/app.component.html b/src/app/app.component.html
index b985d54ad..167675262 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -148,6 +148,11 @@
             33- Real-Time Trading Platform
           </a>
         </li>
+        <li class="nav-item">
+          <a class="nav-link" routerLinkActive="active" [routerLink]="['/header-footer']">
+            34- Custom header &amp; footer templates
+          </a>
+        </li>
       </ul>
     </section>
 
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 37ffc1e9e..ab1fc098a 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -61,6 +61,7 @@ import { AngularSlickgridModule } from './modules/angular-slickgrid/modules/angu
 // load necessary Flatpickr Locale(s), but make sure it's imported AFTER the SlickgridModule import
 import 'flatpickr/dist/l10n/fr';
 import { CustomButtonFormatterComponent } from './examples/custom-buttonFormatter.component';
+import { CustomFooterComponent, GridHeaderFooterComponent } from './examples/grid-header-footer.component';
 
 // AoT requires an exported function for factories
 export function createTranslateLoader(http: HttpClient) {
@@ -130,7 +131,9 @@ export function appInitializerFactory(translate: TranslateService, injector: Inj
     SwtCommonGridTestComponent,
     SwtCommonGridPaginationComponent,
     SwtCommonGridComponent,
-    HomeComponent
+    HomeComponent,
+    GridHeaderFooterComponent,
+    CustomFooterComponent
   ],
   imports: [
     AppRoutingRoutingModule,
diff --git a/src/app/examples/grid-header-footer.component.html b/src/app/examples/grid-header-footer.component.html
new file mode 100644
index 000000000..1023f62e4
--- /dev/null
+++ b/src/app/examples/grid-header-footer.component.html
@@ -0,0 +1,30 @@
+<div id="demo-container" class="container-fluid">
+  <h2>
+    {{ title }}
+    <span class="float-end">
+      <a
+        style="font-size: 18px"
+        target="_blank"
+        href="https://github.com/ghiscoding/Angular-Slickgrid/blob/master/src/app/examples/grid-header-footer.component.ts"
+      >
+        <span class="fa fa-link"></span> code
+      </a>
+    </span>
+  </h2>
+  <div class="subtitle" [innerHTML]="subTitle"></div>
+
+  <angular-slickgrid
+    gridId="grid1"
+    [columnDefinitions]="columnDefinitions"
+    [gridOptions]="gridOptions"
+    [dataset]="dataset"
+  >
+    <ng-template #slickgridHeader>
+      <h3>Grid with header and footer slot</h3>
+    </ng-template>
+
+    <ng-template #slickgridFooter>
+      <custom-footer></custom-footer>
+    </ng-template>
+  </angular-slickgrid>
+</div>
diff --git a/src/app/examples/grid-header-footer.component.ts b/src/app/examples/grid-header-footer.component.ts
new file mode 100644
index 000000000..ec8a4b103
--- /dev/null
+++ b/src/app/examples/grid-header-footer.component.ts
@@ -0,0 +1,76 @@
+import { Component, OnInit } from '@angular/core';
+import { Column, GridOption, Formatters } from './../modules/angular-slickgrid';
+
+const NB_ITEMS = 995;
+
+@Component({
+  template: `<button (click)="clickMe()">I'm a button from an Angular component (click me)</button>
+  <div *ngIf="clickedTimes">You've clicked me {{clickedTimes}} time(s)</div>`,
+  selector: 'custom-footer',
+})
+export class CustomFooterComponent {
+  clickedTimes = 0;
+
+  clickMe() {
+    this.clickedTimes++;
+  }
+}
+
+@Component({
+  templateUrl: './grid-header-footer.component.html',
+})
+export class GridHeaderFooterComponent implements OnInit {
+  title = 'Example 34: Custom header & footer Templates';
+  subTitle = `
+    Basic Grid with templates for custom headers and footers
+    <ul>
+      <li>Pass in custom templates to be rendered at predefined header and footer destinations</li>
+    </ul>
+  `;
+
+  columnDefinitions: Column[] = [];
+  gridOptions!: GridOption;
+  dataset!: any[];
+
+  ngOnInit(): void {
+    this.columnDefinitions = [
+      { id: 'title', name: 'Title', field: 'title', sortable: true },
+      { id: 'duration', name: 'Duration (days)', field: 'duration', sortable: true },
+      { id: '%', name: '% Complete', field: 'percentComplete', sortable: true },
+      { id: 'start', name: 'Start', field: 'start', formatter: Formatters.dateIso },
+      { id: 'finish', name: 'Finish', field: 'finish', formatter: Formatters.dateIso },
+      { id: 'effort-driven', name: 'Effort Driven', field: 'effortDriven', sortable: true }
+    ];
+    this.gridOptions = {
+      enableAutoResize: false,
+      enableSorting: true,
+      gridHeight: 225,
+      gridWidth: 800,
+    };
+
+    this.dataset = this.mockData(NB_ITEMS);
+  }
+
+  mockData(count: number) {
+    // mock a dataset
+    const mockDataset = [];
+    for (let i = 0; i < count; i++) {
+      const randomYear = 2000 + Math.floor(Math.random() * 10);
+      const randomMonth = Math.floor(Math.random() * 11);
+      const randomDay = Math.floor((Math.random() * 29));
+      const randomPercent = Math.round(Math.random() * 100);
+
+      mockDataset[i] = {
+        id: i,
+        title: 'Task ' + i,
+        duration: Math.round(Math.random() * 100) + '',
+        percentComplete: randomPercent,
+        start: new Date(randomYear, randomMonth + 1, randomDay),
+        finish: new Date(randomYear + 1, randomMonth + 1, randomDay),
+        effortDriven: (i % 5 === 0)
+      };
+    }
+
+    return mockDataset;
+  }
+}