dhtmlxGantt mit Angular

Um mit dieser Dokumentation zu arbeiten, ist es hilfreich, ein grundlegendes Verständnis von Angular-Konzepten und -Mustern zu haben. Wenn Sie neu bei Angular sind, werfen Sie einen Blick auf die Angular-Dokumentation für einen schnellen Einstieg.

DHTMLX Gantt integriert sich gut mit Angular. Wir haben einige Beispiele zusammengestellt, um zu demonstrieren, wie man DHTMLX Gantt in Angular-Projekten verwendet. Sie können diese Beispiele online über Replit erkunden oder sich die Demo auf GitHub ansehen.

Einrichten eines Projekts

Bevor Sie loslegen, stellen Sie sicher, dass Sie Angular CLI und Node.js installiert haben.

Um ein neues Angular-Projekt zu erstellen, führen Sie folgenden Befehl aus:

ng new my-angular-gantt-app

Dieser Befehl installiert alle notwendigen Tools und Abhängigkeiten, sodass keine zusätzliche Einrichtung erforderlich ist.

Abhängigkeiten installieren

Navigieren Sie zu Ihrem Projektverzeichnis:

cd my-angular-gantt-app

Führen Sie die Anwendung mit einem der folgenden Befehle aus:

yarn start

oder

npm start

Die App ist nun unter http://localhost:4200 verfügbar.

Gantt Angular app running

Hinzufügen von Gantt zur Anwendung

Um DHTMLX Gantt in Ihre App einzubinden, müssen Sie zuerst die laufende Anwendung stoppen, indem Sie Strg+C im Terminal drücken. Folgen Sie dann den untenstehenden Schritten.

Schritt 1: Installieren des Pakets

Die PRO-Versionen der Bibliothek sind über npm/yarn aus unserem privaten Repository verfügbar. Schauen Sie sich diese Anleitung an, um darauf zuzugreifen.

Sobald Sie die Evaluationsversion von Gantt haben, installieren Sie sie mit:

  • Für npm:
npm install @dhx/trial-gantt
  • Für yarn:
yarn add @dhx/trial-gantt

Alternativ können Sie, wenn Sie ein Zip-Paket der Bibliothek haben, dieses lokal installieren.

Schritt 2: Erstellen einer Gantt-Komponente

Erstellen Sie einen neuen Ordner namens gantt im Verzeichnis src/app/. Erstellen Sie in diesem Ordner zwei Dateien: gantt.component.ts und gantt.component.css.

Importieren von Quelldateien

Importieren Sie in gantt.component.ts die notwendigen Gantt-Quelldateien. Je nach Ihrer Installationsmethode unterscheiden sich die Importpfade:

  • Wenn Sie Gantt aus einem lokalen Ordner installiert haben:
import { Gantt } from 'dhtmlx-gantt';
@import "@dhtmlx-gantt/codebase/dhtmlxgantt.css";
  • Wenn Sie die Testversion installiert haben:
import { Gantt } from '@dhx/trial-gantt';
@import "@dhx/trial-gantt/codebase/dhtmlxgantt.css";

In diesem Beispiel verwenden wir die Testversion.

Fügen Sie nun in gantt.component.ts den folgenden Code ein, um das Gantt-Template einzurichten:

import { Component, ElementRef, OnInit, 
    ViewChild, ViewEncapsulation } from '@angular/core';
import { Gantt, GanttStatic } from "@dhx/trial-gantt";
 
@Component({
    encapsulation: ViewEncapsulation.None,
    selector: 'gantt',
    styleUrls: ['./gantt.component.css'],
    template: `<div #gantt_here class='gantt-chart'></div>`,
})
export class GanttComponent implements OnInit {
    @ViewChild('gantt_here', { static: true }) ganttContainer!: ElementRef;
    private _gantt?: GanttStatic;
 
    ngOnInit() {
        let gantt = Gantt.getGanttInstance();
        gantt.init(this.ganttContainer.nativeElement);
 
        this._gantt = gantt;
    }
    ngOnDestroy() {
        if (this._gantt) this._gantt.destructor();
    }
}

Dieser Code verwendet die ngOnInit() Methode von Angular, um die Gantt-Instanz zu initialisieren, und die ngOnDestroy() Methode, um die Komponente zu bereinigen, wenn sie nicht mehr verwendet wird.

Für die Stile können Sie in gantt.component.css Folgendes hinzufügen:

@import "@dhx/trial-gantt/codebase/dhtmlxgantt.css";
.gantt-chart {
    position: relative;
    width: 100%;
    height: 600px;
}

Schritt 3: Integrieren von Gantt in die App

Um die Gantt-Komponente in Ihre App einzubinden, aktualisieren Sie src/app/app.component.ts mit folgendem Inhalt:

import { Component } from '@angular/core';
 
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'DHTMLX Gantt with Angular';
}

Als nächstes registrieren Sie in src/app/app.module.ts die GanttComponent wie folgt:

import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
 
import { AppComponent } from "./app.component";
import { GanttComponent } from './gantt/gantt.component';
 
@NgModule({
  declarations: [AppComponent, GanttComponent],
  imports: [BrowserModule],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}

Ersetzen Sie in src/app/app.component.html den Standardinhalt durch:

<gantt></gantt>

Zuletzt aktualisieren Sie in src/main.ts den Code wie folgt:

import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";
import { AppModule } from "./app/app.module";
 
platformBrowserDynamic()
  .bootstrapModule(AppModule)
  .catch((err) => console.error(err));

Nachdem alle Änderungen vorgenommen wurden, starten Sie die Anwendung erneut. Sie sollten nun ein leeres Gantt-Diagramm auf der Seite sehen.

Gantt Angular init

Schritt 4. Bereitstellen von Daten

Um Daten in das Angular Gantt zu laden, müssen Sie Task- und Link-Services einrichten. Zuerst definieren wir die Task- und Link-Modelle.

Um diese Modelle zu erstellen, führen Sie die folgenden Befehle aus:

ng generate class models/task --skip-tests
ng generate class models/link --skip-tests

Fügen Sie in der neu erstellten task.ts-Datei im models Ordner den folgenden Code ein:

models/task.ts

export class Task {
    id!: number;
    start_date!: string;
    text!: string;
    progress!: number;
    duration!: number;
    parent!: number;
}

Ähnlich dazu fügen Sie in der link.ts-Datei im models Ordner diesen Code hinzu:

models/link.ts

export class Link {
    id!: number;
    source!: number;
    target!: number;
    type!: string;
}

Als nächstes erstellen Sie Task- und Link-Services. Diese Services sind dafür verantwortlich, Tasks oder Links zu generieren. Angular-Services verwenden Dependency Injection, um Daten, Funktionen oder andere Features für die Anwendung bereitzustellen. Sie benötigen einen Datenservice, um Tasks und Links an das Gantt zu liefern.

Um diese Services zu erstellen, führen Sie folgende Befehle aus:

ng generate service services/task --flat --skip-tests
ng generate service services/link --flat --skip-tests

Fügen Sie in der neu erstellten task.service.ts-Datei im services Ordner diesen Code hinzu:

services/task.service.ts

import { Injectable } from '@angular/core';
import { Task } from '../models/task';
 
@Injectable()
export class TaskService {
    get(): Promise<Task[]> {
        return Promise.resolve([
            { id: 1, text: 'Task #1', start_date: '2023-04-15 00:00', 
                duration: 3, progress: 0.6, parent: 0 },
            { id: 2, text: 'Task #2', start_date: '2023-04-18 00:00', 
                duration: 3, progress: 0.4, parent: 0 }
        ]);
    }
}

Für die link.service.ts-Datei im selben services Ordner fügen Sie Folgendes hinzu:

services/link.service.ts

import { Injectable } from '@angular/core';
import { Link } from '../models/link';
 
@Injectable()
export class LinkService {
    get(): Promise<Link[]> {
        return Promise.resolve([
            { id: 1, source: 1, target: 2, type: '0' }
        ]);
    }
}

Der @Injectable() Dekorator wird hier verwendet, um den Service für die Dependency Injection verfügbar zu machen. Diese Services werden später in die Gantt-Komponente injiziert.

Vorläufig stellt die get() Methode fest kodierte Daten über ein aufgelöstes Promise bereit. Sie können sie jedoch anpassen, um Daten von einem Server abzurufen und ein Promise zurückzugeben. Die Gantt-Komponente wird TaskService und LinkService verwenden, um Tasks und Links abzurufen.

Um dies zu ermöglichen, importieren Sie die notwendigen Module in gantt.component.ts:

gantt.component.ts

import { TaskService } from "../services/task.service";
import { LinkService } from "../services/link.service";

Fügen Sie dann TaskService und LinkService als Anbieter im @Component Dekorator hinzu:

gantt.component.ts

@Component({
    encapsulation: ViewEncapsulation.None,
    selector: 'gantt',
    styleUrls: ['./gantt.component.css'],
    providers: [TaskService, LinkService],
    template: `<div #gantt_here class='gantt-chart'></div>`,
})

Dies stellt sicher, dass jedes Mal, wenn eine GanttComponent initialisiert wird, eine neue Instanz der Services erstellt wird. Um die Services für die Injection vorzubereiten, fügen Sie der GanttComponent Klasse den folgenden Konstruktor hinzu:

gantt.component.ts

constructor(private taskService: TaskService, private linkService: LinkService) { }

Aktualisieren Sie die ngOnInit() Funktion, um:

  • Das Datenformat für das Laden von Tasks festzulegen (in diesem Beispiel XML).
  • Die Services aufzurufen, um Daten abzurufen und auf die Antwort zu warten, bevor sie in das Gantt geladen wird.

gantt.component.ts

let gantt = Gantt.getGanttInstance();
gantt.config.date_format = '%Y-%m-%d %H:%i';
gantt.init(this.ganttContainer.nativeElement);
 
Promise.all([this.taskService.get(), this.linkService.get()])
    .then(([data, links]) => {
        gantt.parse({ data, links });
    });
this._gantt = gantt;

Hier ist der vollständige Code für gantt.component.ts:

gantt.component.ts

import { Component, ElementRef, OnInit, 
    ViewChild, ViewEncapsulation } from '@angular/core';
import { TaskService } from '../services/task.service';
import { LinkService } from '../services/link.service';
import { Gantt, GanttStatic } from "@dhx/trial-gantt";
 
@Component({
    encapsulation: ViewEncapsulation.None,
    selector: 'gantt',
    styleUrls: ['./gantt.component.css'],
    providers: [TaskService, LinkService],
    template: `<div #gantt_here class='gantt-chart'></div>`,
})
export class GanttComponent implements OnInit {
    @ViewChild('gantt_here', { static: true }) ganttContainer!: ElementRef;
    private _gantt?: GanttStatic;
    constructor(private taskService: TaskService, private linkService: LinkService) { }
 
    ngOnInit() {
        let gantt = Gantt.getGanttInstance();
        gantt.config.date_format = '%Y-%m-%d %H:%i';
        gantt.init(this.ganttContainer.nativeElement);
        Promise.all([this.taskService.get(), this.linkService.get()])
            .then(([data, links]) => {
                gantt.parse({ data, links });
            });
        this._gantt = gantt;
    }
    ngOnDestroy() {
        if (this._gantt) this._gantt.destructor();
    }
}

Nachdem Sie dies abgeschlossen haben, sollten Sie beim Neuladen der App-Seite das Gantt-Diagramm mit Tasks gefüllt sehen:

Gantt Angular events

Schritt 5. Speichern von Daten

Um Änderungen im Gantt zu handhaben, können Sie einen dataProcessor Handler verwenden. Dieses Tool ermöglicht die Kommunikation mit dem serverseitigen Backend. Es kann als Funktion oder Router-Objekt eingerichtet werden. Mit dhtmlxGantt unterstützt der Handler Promise-Antworten und stellt so die ordnungsgemäße Handhabung abgeschlossener Aktionen sicher.

Hier erfahren Sie, wie Sie einen DataProcessor mit der createDataProcessor() API-Methode erstellen, um Änderungen zu erfassen:

gantt.createDataProcessor(function(entity, action, data, id) {
    gantt.message(`${entity} ${action}`);
});

Wenn Ihr Service die Task-ID nach dem Erstellen eines neuen Datensatzes ändert (gängige Praxis), stellen Sie sicher, dass das Promise ein Objekt wie {id: databaseId} oder {tid: databaseId} zurückgibt. Dies ermöglicht es Gantt, den Datensatz mit der neuen Datenbank-ID zu aktualisieren. Weitere Details zur serverseitigen Integration finden Sie in der serverseitigen Dokumentation.

Nun ist Ihre Angular Gantt-Einrichtung abgeschlossen! Sie können sich die vollständige Demo auf GitHub ansehen.

XSS-, CSRF- und SQL-Injection-Angriffe

Beachten Sie, dass Gantt keine eingebauten Schutzmaßnahmen gegen Bedrohungen wie SQL-Injection, XSS oder CSRF-Angriffe enthält. Die Sicherstellung der Anwendungssicherheit liegt in der Verantwortung der Backend-Entwickler.

Für Leitlinien zur Sicherung Ihrer Anwendung werfen Sie einen Blick auf den Artikel Application Security, der häufige Schwachstellen und Möglichkeiten zu deren Minderung beschreibt.

Zurück nach oben