Synchronizing multiple graphics

lenormor

Gaetan Gasoline

Posted on June 18, 2024

Synchronizing multiple graphics

Step 1: Define our objective

To keep things simple let’s set our objective first:

We want to combine two instances of our <demo-schedule-booking> demonstration component. This component is capable of displaying a ScheduleJS Gantt chart.
Note that the same approach can be used with two completely different graphics.

Step 2: Create a higher-order ‘dual-gantt’ component

A good idea is to use a containerized version of our graphics to be able to handle the display of multiple graphics with ease, using components.

Now let’s start by creating a dual-gantt component and try out our component.

<!-- Let's start with one graphic at a time -->
<demo-schedule-booking><demo-schedule-booking/>
Enter fullscreen mode Exit fullscreen mode

Fow now, if our <demo-schedule-booking> component is functional, our dual-gantt component will display the following screen, which is in fact identical to the original component.

JS Gantt

Now we can create a <div> and use our <demo-schedule-booking> component twice in our brand new dual-gantt component:

<!-- Let's assemble two ScheduleJS demo bookings in our component -->

<div class="gantts-container">

  <demo-schedule-booking class="first-gantt"></demo-schedule-booking>

  <demo-schedule-booking class="second-gantt"></demo-schedule-booking>

</div>
Enter fullscreen mode Exit fullscreen mode

We added CSS classes to properly display one graphic above the other and separate them with a border. Here, the gantts-container class handles the display while the first-gantt and the second-gantt classes handle specificities, like the separation border.

We now have two unsynchronized graphics inside our new dual-gantt component:

JS Gantt

To further improve the display, we adapted our <demo-schedule-booking> component to accept two new input properties:

  • displayTimeline: True by default, as we are going to use a single timeline, it is not necessary to repeat the timeline in both graphics.
  • displayButtonBar: True by default, will let us hide the button bar to only keep one button bar for both graphics.

As a ScheduleJS Gantt component, <demo-schedule-booking> also accepts additional inputs by default. Here we will use the dragToResizeInfoColumnPrevented input property to prevent any individual info-column resize for both graphics. The result should get rid of the button bar and timeline for the second graphics:

<!-- Let's add a few properties to better handle the dual-gantt display -->

<div class="gantts-container">

  <demo-schedule-booking class="first-gantt"
                         [dragToResizeInfoColumnPrevented]="true">
  </demo-schedule-booking>

  <demo-schedule-booking class="second-gantt"
                         [displayTimeline]="false"
                         [displayButtonBar]="false"
                         [dragToResizeInfoColumnPrevented]="true">
  </demo-schedule-booking>

</div>
Enter fullscreen mode Exit fullscreen mode

JS Gantt

Step 3: Share a single timeline object

We want to create a new timeline object and pass it down to our graphics once our dual-gantt component mounts. Here is the source code of our dual-gantt component:

// Our dual-gantt component
import {Component, Injector} from "@angular/core";
import {Timeline} from "schedule";

@Component({
  selector: "dual-gantt",
  templateUrl: "./dual-gantt.component.html",
  styleUrls: ["./dual-gantt.component.scss"]
})
export class DualGanttComponent {

  // Here we create a single timeline, which requires the Angular Injector
  readonly timeline: Timeline = new Timeline(this._injector);

  // Use dependency injection to provide an instance of the Angular Injector
  constructor(private readonly _injector: Injector) { }

}
Enter fullscreen mode Exit fullscreen mode

Now we have to pass down our new timeline object as an input to our <demo-schedule-booking> ScheduleJS Gantt component in the dual-gantt component template:

<!-- Pass our freshly instanciated timeline object for registration in both components -->

<div class="gantts-container">

  <demo-schedule-booking class="first-gantt"
                         [timeline]="timeline"
                         [dragToResizeInfoColumnPrevented]="true">
  </demo-schedule-booking>

  <demo-schedule-booking class="second-gantt"
                         [timeline]="timeline"           
                         [displayTimeline]="false"
                         [displayButtonBar]="false"
                         [dragToResizeInfoColumnPrevented]="true">
  </demo-schedule-booking>

</div>
Enter fullscreen mode Exit fullscreen mode

Step 4: Register the timeline using the ScheduleJS API

The last step is to register the timeline in the <demo-schedule-booking> component.

To do so, we decided to create a setter method, which will run the registration code when the input is passed down to the component:

export class DemoBookingComponent extends DefaultScheduleTreeGanttComponentBase<ResourceRow, DefaultScheduleGanttGraphicTreeComponent<ResourceRow>> {

  // [...]

  // Register the given timeline or do nothing 
  @Input()
  set timeline(timeline: Timeline | undefined) {
    if (timeline) {
      this.gantt.setTimeline(timeline);
      this.gantt.getGraphics().setTimeline(timeline);
    }
  }

  // [...]

}
Enter fullscreen mode Exit fullscreen mode

Conclusion

By creating a dual-Gantt component, we have successfully combined two instances of the <demo-schedule-booking> component into a cohesive and synchronized display. This approach not only enhances the visual representation of Gantt charts but also improves the user experience by sharing a single timeline and reducing redundancy. Leveraging the powerful features of ScheduleJS, we can efficiently manage complex project schedules with greater interactivity and customization. This method demonstrates how flexible and dynamic JavaScript Gantt charts can be, making them indispensable tools for modern project management.

If you'd like to see the final result, don't hesitate to take a look at: Synchronizing multiple graphics

For more information on JS Gantt see: ScheduleJS

💖 💪 🙅 🚩
lenormor
Gaetan Gasoline

Posted on June 18, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related